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
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