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
2796576e
Commit
2796576e
authored
Feb 17, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge home.transmeta.com:/home/torvalds/v2.5/morton
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
98d809e7
071c9b22
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
237 additions
and
94 deletions
+237
-94
fs/block_dev.c
fs/block_dev.c
+9
-5
fs/buffer.c
fs/buffer.c
+119
-16
fs/ext2/dir.c
fs/ext2/dir.c
+7
-2
fs/minix/dir.c
fs/minix/dir.c
+15
-10
fs/nfs/file.c
fs/nfs/file.c
+8
-3
fs/sysv/ChangeLog
fs/sysv/ChangeLog
+7
-0
fs/sysv/dir.c
fs/sysv/dir.c
+7
-2
include/linux/fs.h
include/linux/fs.h
+4
-3
kernel/ksyms.c
kernel/ksyms.c
+0
-1
mm/filemap.c
mm/filemap.c
+61
-52
No files found.
fs/block_dev.c
View file @
2796576e
...
...
@@ -195,11 +195,15 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
static
int
__block_fsync
(
struct
inode
*
inode
)
{
int
ret
;
filemap_fdatasync
(
inode
->
i_mapping
);
ret
=
sync_buffers
(
inode
->
i_rdev
,
1
);
filemap_fdatawait
(
inode
->
i_mapping
);
int
ret
,
err
;
ret
=
filemap_fdatasync
(
inode
->
i_mapping
);
err
=
sync_buffers
(
inode
->
i_rdev
,
1
);
if
(
err
&&
!
ret
)
ret
=
err
;
err
=
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
err
&&
!
ret
)
ret
=
err
;
return
ret
;
}
...
...
fs/buffer.c
View file @
2796576e
...
...
@@ -410,9 +410,9 @@ asmlinkage long sys_fsync(unsigned int fd)
struct
file
*
file
;
struct
dentry
*
dentry
;
struct
inode
*
inode
;
int
err
;
int
ret
,
err
;
err
=
-
EBADF
;
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
!
file
)
goto
out
;
...
...
@@ -420,21 +420,27 @@ asmlinkage long sys_fsync(unsigned int fd)
dentry
=
file
->
f_dentry
;
inode
=
dentry
->
d_inode
;
err
=
-
EINVAL
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
fsync
)
ret
=
-
EINVAL
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
fsync
)
{
/* Why? We can still call filemap_fdatasync */
goto
out_putf
;
}
/* We need to protect against concurrent writers.. */
down
(
&
inode
->
i_sem
);
filemap_fdatasync
(
inode
->
i_mapping
);
ret
=
filemap_fdatasync
(
inode
->
i_mapping
);
err
=
file
->
f_op
->
fsync
(
file
,
dentry
,
0
);
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
err
&&
!
ret
)
ret
=
err
;
err
=
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
err
&&
!
ret
)
ret
=
err
;
up
(
&
inode
->
i_sem
);
out_putf:
fput
(
file
);
out:
return
err
;
return
ret
;
}
asmlinkage
long
sys_fdatasync
(
unsigned
int
fd
)
...
...
@@ -442,9 +448,9 @@ asmlinkage long sys_fdatasync(unsigned int fd)
struct
file
*
file
;
struct
dentry
*
dentry
;
struct
inode
*
inode
;
int
err
;
int
ret
,
err
;
err
=
-
EBADF
;
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
!
file
)
goto
out
;
...
...
@@ -452,20 +458,24 @@ asmlinkage long sys_fdatasync(unsigned int fd)
dentry
=
file
->
f_dentry
;
inode
=
dentry
->
d_inode
;
err
=
-
EINVAL
;
ret
=
-
EINVAL
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
fsync
)
goto
out_putf
;
down
(
&
inode
->
i_sem
);
filemap_fdatasync
(
inode
->
i_mapping
);
ret
=
filemap_fdatasync
(
inode
->
i_mapping
);
err
=
file
->
f_op
->
fsync
(
file
,
dentry
,
1
);
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
err
&&
!
ret
)
ret
=
err
;
err
=
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
err
&&
!
ret
)
ret
=
err
;
up
(
&
inode
->
i_sem
);
out_putf:
fput
(
file
);
out:
return
err
;
return
ret
;
}
/* After several hours of tedious analysis, the following hash
...
...
@@ -1431,6 +1441,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
int
err
,
i
;
unsigned
long
block
;
struct
buffer_head
*
bh
,
*
head
;
int
need_unlock
;
if
(
!
PageLocked
(
page
))
BUG
();
...
...
@@ -1486,7 +1497,33 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
return
0
;
out:
/*
* ENOSPC, or some other error. We may already have added some
* blocks to the file, so we need to write these out to avoid
* exposing stale data.
*/
ClearPageUptodate
(
page
);
bh
=
head
;
need_unlock
=
1
;
/* Recovery: lock and submit the mapped buffers */
do
{
if
(
buffer_mapped
(
bh
))
{
lock_buffer
(
bh
);
set_buffer_async_io
(
bh
);
need_unlock
=
0
;
}
bh
=
bh
->
b_this_page
;
}
while
(
bh
!=
head
);
do
{
struct
buffer_head
*
next
=
bh
->
b_this_page
;
if
(
buffer_mapped
(
bh
))
{
set_bit
(
BH_Uptodate
,
&
bh
->
b_state
);
clear_bit
(
BH_Dirty
,
&
bh
->
b_state
);
submit_bh
(
WRITE
,
bh
);
}
bh
=
next
;
}
while
(
bh
!=
head
);
if
(
need_unlock
)
UnlockPage
(
page
);
return
err
;
}
...
...
@@ -1518,6 +1555,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
continue
;
if
(
block_start
>=
to
)
break
;
clear_bit
(
BH_New
,
&
bh
->
b_state
);
if
(
!
buffer_mapped
(
bh
))
{
err
=
get_block
(
inode
,
block
,
bh
,
1
);
if
(
err
)
...
...
@@ -1552,12 +1590,35 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
*/
while
(
wait_bh
>
wait
)
{
wait_on_buffer
(
*--
wait_bh
);
err
=
-
EIO
;
if
(
!
buffer_uptodate
(
*
wait_bh
))
goto
out
;
return
-
EIO
;
}
return
0
;
out:
/*
* Zero out any newly allocated blocks to avoid exposing stale
* data. If BH_New is set, we know that the block was newly
* allocated in the above loop.
*/
bh
=
head
;
block_start
=
0
;
do
{
block_end
=
block_start
+
blocksize
;
if
(
block_end
<=
from
)
goto
next_bh
;
if
(
block_start
>=
to
)
break
;
if
(
buffer_new
(
bh
))
{
if
(
buffer_uptodate
(
bh
))
printk
(
KERN_ERR
"%s: zeroing uptodate buffer!
\n
"
,
__FUNCTION__
);
memset
(
kaddr
+
block_start
,
0
,
bh
->
b_size
);
set_bit
(
BH_Uptodate
,
&
bh
->
b_state
);
mark_buffer_dirty
(
bh
);
}
next_bh:
block_start
=
block_end
;
bh
=
bh
->
b_this_page
;
}
while
(
bh
!=
head
);
return
err
;
}
...
...
@@ -1954,6 +2015,48 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
goto
done
;
}
/*
* Commence writeout of all the buffers against a page. The
* page must be locked. Returns zero on success or a negative
* errno.
*/
int
writeout_one_page
(
struct
page
*
page
)
{
struct
buffer_head
*
bh
,
*
head
=
page
->
buffers
;
if
(
!
PageLocked
(
page
))
BUG
();
bh
=
head
;
do
{
if
(
buffer_locked
(
bh
)
||
!
buffer_dirty
(
bh
)
||
!
buffer_uptodate
(
bh
))
continue
;
bh
->
b_flushtime
=
jiffies
;
ll_rw_block
(
WRITE
,
1
,
&
bh
);
}
while
((
bh
=
bh
->
b_this_page
)
!=
head
);
return
0
;
}
EXPORT_SYMBOL
(
writeout_one_page
);
/*
* Wait for completion of I/O of all buffers against a page. The page
* must be locked. Returns zero on success or a negative errno.
*/
int
waitfor_one_page
(
struct
page
*
page
)
{
int
error
=
0
;
struct
buffer_head
*
bh
,
*
head
=
page
->
buffers
;
bh
=
head
;
do
{
wait_on_buffer
(
bh
);
if
(
buffer_req
(
bh
)
&&
!
buffer_uptodate
(
bh
))
error
=
-
EIO
;
}
while
((
bh
=
bh
->
b_this_page
)
!=
head
);
return
error
;
}
EXPORT_SYMBOL
(
waitfor_one_page
);
sector_t
generic_block_bmap
(
struct
address_space
*
mapping
,
sector_t
block
,
get_block_t
*
get_block
)
{
...
...
fs/ext2/dir.c
View file @
2796576e
...
...
@@ -52,8 +52,13 @@ static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
int
err
=
0
;
dir
->
i_version
=
++
event
;
page
->
mapping
->
a_ops
->
commit_write
(
NULL
,
page
,
from
,
to
);
if
(
IS_SYNC
(
dir
))
err
=
waitfor_one_page
(
page
);
if
(
IS_SYNC
(
dir
))
{
int
err2
;
err
=
writeout_one_page
(
page
);
err2
=
waitfor_one_page
(
page
);
if
(
err
==
0
)
err
=
err2
;
}
return
err
;
}
...
...
fs/minix/dir.c
View file @
2796576e
...
...
@@ -36,8 +36,13 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
struct
inode
*
dir
=
(
struct
inode
*
)
page
->
mapping
->
host
;
int
err
=
0
;
page
->
mapping
->
a_ops
->
commit_write
(
NULL
,
page
,
from
,
to
);
if
(
IS_SYNC
(
dir
))
err
=
waitfor_one_page
(
page
);
if
(
IS_SYNC
(
dir
))
{
int
err2
;
err
=
writeout_one_page
(
page
);
err2
=
waitfor_one_page
(
page
);
if
(
err
==
0
)
err
=
err2
;
}
return
err
;
}
...
...
@@ -236,10 +241,10 @@ int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
lock_page
(
page
);
err
=
mapping
->
a_ops
->
prepare_write
(
NULL
,
page
,
from
,
to
);
if
(
err
)
BUG
();
if
(
err
==
0
)
{
de
->
inode
=
0
;
err
=
dir_commit_chunk
(
page
,
from
,
to
);
}
UnlockPage
(
page
);
dir_put_page
(
page
);
inode
->
i_ctime
=
inode
->
i_mtime
=
CURRENT_TIME
;
...
...
@@ -336,10 +341,10 @@ void minix_set_link(struct minix_dir_entry *de, struct page *page,
lock_page
(
page
);
err
=
page
->
mapping
->
a_ops
->
prepare_write
(
NULL
,
page
,
from
,
to
);
if
(
err
)
BUG
();
if
(
err
==
0
)
{
de
->
inode
=
inode
->
i_ino
;
err
=
dir_commit_chunk
(
page
,
from
,
to
);
}
UnlockPage
(
page
);
dir_put_page
(
page
);
dir
->
i_mtime
=
dir
->
i_ctime
=
CURRENT_TIME
;
...
...
fs/nfs/file.c
View file @
2796576e
...
...
@@ -244,6 +244,7 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct
inode
*
inode
=
filp
->
f_dentry
->
d_inode
;
int
status
=
0
;
int
status2
;
dprintk
(
"NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)
\n
"
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
,
...
...
@@ -278,11 +279,15 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
* Flush all pending writes before doing anything
* with locks..
*/
filemap_fdatasync
(
inode
->
i_mapping
);
status
=
filemap_fdatasync
(
inode
->
i_mapping
);
down
(
&
inode
->
i_sem
);
status
=
nfs_wb_all
(
inode
);
status2
=
nfs_wb_all
(
inode
);
if
(
status2
&&
!
status
)
status
=
status2
;
up
(
&
inode
->
i_sem
);
filemap_fdatawait
(
inode
->
i_mapping
);
status2
=
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
status2
&&
!
status
)
status
=
status2
;
if
(
status
<
0
)
return
status
;
...
...
fs/sysv/ChangeLog
View file @
2796576e
Thu Feb 14 2002 Andrew Morton <akpm@zip.com.au>
* dir_commit_chunk(): call writeout_one_page() as well as
waitfor_one_page() for IS_SYNC directories, so that we
actually do sync the directory. (forward-port from 2.4).
Thu Feb 7 2002 Alexander Viro <viro@math.psu.edu>
* super.c: switched to ->get_sb()
...
...
@@ -97,3 +103,4 @@ Fri Oct 26 2001 Christoph Hellwig <hch@caldera.de>
Remove symlink faking. Noone really wants to use these as
linux filesystems and native OSes don't support it anyway.
fs/sysv/dir.c
View file @
2796576e
...
...
@@ -42,8 +42,13 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
int
err
=
0
;
page
->
mapping
->
a_ops
->
commit_write
(
NULL
,
page
,
from
,
to
);
if
(
IS_SYNC
(
dir
))
err
=
waitfor_one_page
(
page
);
if
(
IS_SYNC
(
dir
))
{
int
err2
;
err
=
writeout_one_page
(
page
);
err2
=
waitfor_one_page
(
page
);
if
(
err
==
0
)
err
=
err2
;
}
return
err
;
}
...
...
include/linux/fs.h
View file @
2796576e
...
...
@@ -1230,8 +1230,8 @@ static inline int fsync_inode_data_buffers(struct inode *inode)
return
fsync_buffers_list
(
&
inode
->
i_dirty_data_buffers
);
}
extern
int
inode_has_buffers
(
struct
inode
*
);
extern
void
filemap_fdatasync
(
struct
address_space
*
);
extern
void
filemap_fdatawait
(
struct
address_space
*
);
extern
int
filemap_fdatasync
(
struct
address_space
*
);
extern
int
filemap_fdatawait
(
struct
address_space
*
);
extern
void
sync_supers
(
kdev_t
);
extern
int
bmap
(
struct
inode
*
,
int
);
extern
int
notify_change
(
struct
dentry
*
,
struct
iattr
*
);
...
...
@@ -1440,8 +1440,9 @@ sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
int
generic_commit_write
(
struct
file
*
,
struct
page
*
,
unsigned
,
unsigned
);
int
block_truncate_page
(
struct
address_space
*
,
loff_t
,
get_block_t
*
);
extern
int
generic_direct_IO
(
int
,
struct
inode
*
,
struct
kiobuf
*
,
unsigned
long
,
int
,
get_block_t
*
);
extern
int
waitfor_one_page
(
struct
page
*
);
extern
int
writeout_one_page
(
struct
page
*
);
extern
int
waitfor_one_page
(
struct
page
*
);
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
*
);
...
...
kernel/ksyms.c
View file @
2796576e
...
...
@@ -213,7 +213,6 @@ EXPORT_SYMBOL(cont_prepare_write);
EXPORT_SYMBOL
(
generic_commit_write
);
EXPORT_SYMBOL
(
block_truncate_page
);
EXPORT_SYMBOL
(
generic_block_bmap
);
EXPORT_SYMBOL
(
waitfor_one_page
);
EXPORT_SYMBOL
(
generic_file_read
);
EXPORT_SYMBOL
(
do_generic_file_read
);
EXPORT_SYMBOL
(
generic_file_write
);
...
...
mm/filemap.c
View file @
2796576e
...
...
@@ -449,41 +449,6 @@ static inline struct page * __find_page_nolock(struct address_space *mapping, un
return
page
;
}
/*
* By the time this is called, the page is locked and
* we don't have to worry about any races any more.
*
* Start the IO..
*/
static
int
writeout_one_page
(
struct
page
*
page
)
{
struct
buffer_head
*
bh
,
*
head
=
page
->
buffers
;
bh
=
head
;
do
{
if
(
buffer_locked
(
bh
)
||
!
buffer_dirty
(
bh
)
||
!
buffer_uptodate
(
bh
))
continue
;
bh
->
b_flushtime
=
jiffies
;
ll_rw_block
(
WRITE
,
1
,
&
bh
);
}
while
((
bh
=
bh
->
b_this_page
)
!=
head
);
return
0
;
}
int
waitfor_one_page
(
struct
page
*
page
)
{
int
error
=
0
;
struct
buffer_head
*
bh
,
*
head
=
page
->
buffers
;
bh
=
head
;
do
{
wait_on_buffer
(
bh
);
if
(
buffer_req
(
bh
)
&&
!
buffer_uptodate
(
bh
))
error
=
-
EIO
;
}
while
((
bh
=
bh
->
b_this_page
)
!=
head
);
return
error
;
}
static
int
do_buffer_fdatasync
(
struct
list_head
*
head
,
unsigned
long
start
,
unsigned
long
end
,
int
(
*
fn
)(
struct
page
*
))
{
struct
list_head
*
curr
;
...
...
@@ -577,8 +542,9 @@ EXPORT_SYMBOL(fail_writepage);
* @mapping: address space structure to write
*
*/
void
filemap_fdatasync
(
struct
address_space
*
mapping
)
int
filemap_fdatasync
(
struct
address_space
*
mapping
)
{
int
ret
=
0
;
int
(
*
writepage
)(
struct
page
*
)
=
mapping
->
a_ops
->
writepage
;
spin_lock
(
&
pagecache_lock
);
...
...
@@ -598,8 +564,11 @@ void filemap_fdatasync(struct address_space * mapping)
lock_page
(
page
);
if
(
PageDirty
(
page
))
{
int
err
;
ClearPageDirty
(
page
);
writepage
(
page
);
err
=
writepage
(
page
);
if
(
err
&&
!
ret
)
ret
=
err
;
}
else
UnlockPage
(
page
);
...
...
@@ -607,6 +576,7 @@ void filemap_fdatasync(struct address_space * mapping)
spin_lock
(
&
pagecache_lock
);
}
spin_unlock
(
&
pagecache_lock
);
return
ret
;
}
/**
...
...
@@ -616,8 +586,10 @@ void filemap_fdatasync(struct address_space * mapping)
* @mapping: address space structure to wait for
*
*/
void
filemap_fdatawait
(
struct
address_space
*
mapping
)
int
filemap_fdatawait
(
struct
address_space
*
mapping
)
{
int
ret
=
0
;
spin_lock
(
&
pagecache_lock
);
while
(
!
list_empty
(
&
mapping
->
locked_pages
))
{
...
...
@@ -633,11 +605,14 @@ void filemap_fdatawait(struct address_space * mapping)
spin_unlock
(
&
pagecache_lock
);
___wait_on_page
(
page
);
if
(
PageError
(
page
))
ret
=
-
EIO
;
page_cache_release
(
page
);
spin_lock
(
&
pagecache_lock
);
}
spin_unlock
(
&
pagecache_lock
);
return
ret
;
}
/*
...
...
@@ -1514,12 +1489,14 @@ static ssize_t generic_file_direct_IO(int rw, struct file * filp, char * buf, si
goto
out_free
;
/*
* Flush to disk ex
lusively the _data_, metadata must remains
* Flush to disk ex
clusively the _data_, metadata must remain
* completly asynchronous or performance will go to /dev/null.
*/
filemap_fdatasync
(
mapping
);
retval
=
filemap_fdatasync
(
mapping
);
if
(
retval
==
0
)
retval
=
fsync_inode_data_buffers
(
inode
);
filemap_fdatawait
(
mapping
);
if
(
retval
==
0
)
retval
=
filemap_fdatawait
(
mapping
);
if
(
retval
<
0
)
goto
out_free
;
...
...
@@ -2136,26 +2113,45 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
* The msync() system call.
*/
/*
* MS_SYNC syncs the entire file - including mappings.
*
* MS_ASYNC initiates writeout of just the dirty mapped data.
* This provides no guarantee of file integrity - things like indirect
* blocks may not have started writeout. MS_ASYNC is primarily useful
* where the application knows that it has finished with the data and
* wishes to intelligently schedule its own I/O traffic.
*/
static
int
msync_interval
(
struct
vm_area_struct
*
vma
,
unsigned
long
start
,
unsigned
long
end
,
int
flags
)
{
int
ret
=
0
;
struct
file
*
file
=
vma
->
vm_file
;
if
(
file
&&
(
vma
->
vm_flags
&
VM_SHARED
))
{
int
error
;
error
=
filemap_sync
(
vma
,
start
,
end
-
start
,
flags
);
ret
=
filemap_sync
(
vma
,
start
,
end
-
start
,
flags
);
if
(
!
error
&&
(
flags
&
MS_SYNC
))
{
if
(
!
ret
&&
(
flags
&
(
MS_SYNC
|
MS_ASYNC
)
))
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
down
(
&
inode
->
i_sem
);
filemap_fdatasync
(
inode
->
i_mapping
);
if
(
file
->
f_op
&&
file
->
f_op
->
fsync
)
error
=
file
->
f_op
->
fsync
(
file
,
file
->
f_dentry
,
1
);
filemap_fdatawait
(
inode
->
i_mapping
);
ret
=
filemap_fdatasync
(
inode
->
i_mapping
);
if
(
flags
&
MS_SYNC
)
{
int
err
;
if
(
file
->
f_op
&&
file
->
f_op
->
fsync
)
{
err
=
file
->
f_op
->
fsync
(
file
,
file
->
f_dentry
,
1
);
if
(
err
&&
!
ret
)
ret
=
err
;
}
err
=
filemap_fdatawait
(
inode
->
i_mapping
);
if
(
err
&&
!
ret
)
ret
=
err
;
}
up
(
&
inode
->
i_sem
);
}
return
error
;
}
return
0
;
return
ret
;
}
asmlinkage
long
sys_msync
(
unsigned
long
start
,
size_t
len
,
int
flags
)
...
...
@@ -2999,7 +2995,7 @@ generic_file_write(struct file *file,const char *buf,size_t count, loff_t *ppos)
kaddr
=
kmap
(
page
);
status
=
mapping
->
a_ops
->
prepare_write
(
file
,
page
,
offset
,
offset
+
bytes
);
if
(
status
)
goto
unlock
;
goto
sync_failure
;
page_fault
=
__copy_from_user
(
kaddr
+
offset
,
buf
,
bytes
);
flush_dcache_page
(
page
);
status
=
mapping
->
a_ops
->
commit_write
(
file
,
page
,
offset
,
offset
+
bytes
);
...
...
@@ -3024,6 +3020,7 @@ generic_file_write(struct file *file,const char *buf,size_t count, loff_t *ppos)
if
(
status
<
0
)
break
;
}
while
(
count
);
done:
*
ppos
=
pos
;
if
(
cached_page
)
...
...
@@ -3046,6 +3043,18 @@ generic_file_write(struct file *file,const char *buf,size_t count, loff_t *ppos)
status
=
-
EFAULT
;
goto
unlock
;
sync_failure:
/*
* If blocksize < pagesize, prepare_write() may have instantiated a
* few blocks outside i_size. Trim these off again.
*/
kunmap
(
page
);
UnlockPage
(
page
);
page_cache_release
(
page
);
if
(
pos
+
bytes
>
inode
->
i_size
)
vmtruncate
(
inode
,
inode
->
i_size
);
goto
done
;
o_direct:
written
=
generic_file_direct_IO
(
WRITE
,
file
,
(
char
*
)
buf
,
count
,
pos
);
if
(
written
>
0
)
{
...
...
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