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
f6506d68
Commit
f6506d68
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 2.3.7pre3
parent
2fcc8e43
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1116 additions
and
1046 deletions
+1116
-1046
drivers/char/tty_io.c
drivers/char/tty_io.c
+2
-5
drivers/usb/uhci.c
drivers/usb/uhci.c
+2
-1
fs/buffer.c
fs/buffer.c
+211
-188
fs/ext2/file.c
fs/ext2/file.c
+1
-28
fs/inode.c
fs/inode.c
+0
-4
fs/minix/bitmap.c
fs/minix/bitmap.c
+0
-8
fs/minix/file.c
fs/minix/file.c
+51
-69
fs/minix/inode.c
fs/minix/inode.c
+207
-83
fs/minix/truncate.c
fs/minix/truncate.c
+7
-4
fs/nfs/dir.c
fs/nfs/dir.c
+170
-87
fs/nfs/inode.c
fs/nfs/inode.c
+19
-16
fs/pipe.c
fs/pipe.c
+3
-5
fs/read_write.c
fs/read_write.c
+0
-7
fs/sysv/file.c
fs/sysv/file.c
+56
-205
fs/sysv/inode.c
fs/sysv/inode.c
+110
-43
fs/sysv/truncate.c
fs/sysv/truncate.c
+8
-5
fs/ufs/file.c
fs/ufs/file.c
+84
-175
fs/ufs/inode.c
fs/ufs/inode.c
+128
-41
fs/ufs/truncate.c
fs/ufs/truncate.c
+7
-4
include/linux/fs.h
include/linux/fs.h
+6
-13
include/linux/minix_fs.h
include/linux/minix_fs.h
+1
-0
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+2
-1
include/linux/sysv_fs.h
include/linux/sysv_fs.h
+1
-0
include/linux/ufs_fs.h
include/linux/ufs_fs.h
+1
-0
mm/filemap.c
mm/filemap.c
+39
-54
No files found.
drivers/char/tty_io.c
View file @
f6506d68
...
...
@@ -651,9 +651,7 @@ static inline ssize_t do_tty_write(
ssize_t
ret
=
0
,
written
=
0
;
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
up
(
&
inode
->
i_sem
);
if
(
down_interruptible
(
&
inode
->
i_atomic_write
))
{
down
(
&
inode
->
i_sem
);
if
(
down_interruptible
(
&
inode
->
i_sem
))
{
return
-
ERESTARTSYS
;
}
for
(;;)
{
...
...
@@ -678,8 +676,7 @@ static inline ssize_t do_tty_write(
file
->
f_dentry
->
d_inode
->
i_mtime
=
CURRENT_TIME
;
ret
=
written
;
}
up
(
&
inode
->
i_atomic_write
);
down
(
&
inode
->
i_sem
);
up
(
&
inode
->
i_sem
);
return
ret
;
}
...
...
drivers/usb/uhci.c
View file @
f6506d68
...
...
@@ -1264,7 +1264,8 @@ static void uhci_interrupt_notify(struct uhci *uhci)
struct
uhci_qh
*
interrupt_qh
=
td
->
qh
;
usb_dotoggle
(
td
->
dev
,
usb_pipeendpoint
(
td
->
info
));
td
->
info
|=
1
<<
19
;
/* toggle between data0 and data1 */
td
->
info
&=
~
(
1
<<
19
);
/* clear data toggle */
td
->
info
|=
usb_gettoggle
(
td
->
dev
,
usb_pipeendpoint
(
td
->
info
))
<<
19
;
/* toggle between data0 and data1 */
td
->
status
=
(
td
->
status
&
0x2f000000
)
|
(
1
<<
23
)
|
(
1
<<
24
);
/* active */
/* Remove then readd? Is that necessary */
...
...
fs/buffer.c
View file @
f6506d68
This diff is collapsed.
Click to expand it.
fs/ext2/file.c
View file @
f6506d68
...
...
@@ -108,34 +108,7 @@ static inline void remove_suid(struct inode *inode)
static
int
ext2_writepage
(
struct
file
*
file
,
struct
page
*
page
)
{
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
unsigned
long
block
;
int
*
p
,
nr
[
PAGE_SIZE
/
512
];
int
i
,
err
,
created
;
struct
buffer_head
*
bh
;
i
=
PAGE_SIZE
>>
inode
->
i_sb
->
s_blocksize_bits
;
block
=
page
->
offset
>>
inode
->
i_sb
->
s_blocksize_bits
;
p
=
nr
;
bh
=
page
->
buffers
;
do
{
if
(
bh
&&
bh
->
b_blocknr
)
*
p
=
bh
->
b_blocknr
;
else
*
p
=
ext2_getblk_block
(
inode
,
block
,
1
,
&
err
,
&
created
);
if
(
!*
p
)
return
-
EIO
;
i
--
;
block
++
;
p
++
;
if
(
bh
)
bh
=
bh
->
b_this_page
;
}
while
(
i
>
0
);
/* IO start */
brw_page
(
WRITE
,
page
,
inode
->
i_dev
,
nr
,
inode
->
i_sb
->
s_blocksize
,
1
);
return
0
;
return
block_write_full_page
(
file
,
page
,
ext2_getblk_block
);
}
static
long
ext2_write_one_page
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
bytes
,
const
char
*
buf
)
...
...
fs/inode.c
View file @
f6506d68
...
...
@@ -130,7 +130,6 @@ static inline void init_once(struct inode * inode)
INIT_LIST_HEAD
(
&
inode
->
i_hash
);
INIT_LIST_HEAD
(
&
inode
->
i_dentry
);
sema_init
(
&
inode
->
i_sem
,
1
);
sema_init
(
&
inode
->
i_atomic_write
,
1
);
}
static
inline
void
write_inode
(
struct
inode
*
inode
)
...
...
@@ -767,9 +766,6 @@ kdevname(inode->i_dev), inode->i_ino, inode->i_count);
if
(
atomic_read
(
&
inode
->
i_sem
.
count
)
!=
1
)
printk
(
KERN_ERR
"iput: Aieee, semaphore in use inode %s/%ld, count=%d
\n
"
,
kdevname
(
inode
->
i_dev
),
inode
->
i_ino
,
atomic_read
(
&
inode
->
i_sem
.
count
));
if
(
atomic_read
(
&
inode
->
i_atomic_write
.
count
)
!=
1
)
printk
(
KERN_ERR
"iput: Aieee, atomic write semaphore in use inode %s/%ld, count=%d
\n
"
,
kdevname
(
inode
->
i_dev
),
inode
->
i_ino
,
atomic_read
(
&
inode
->
i_sem
.
count
));
#endif
}
if
(
inode
->
i_count
>
(
1
<<
31
))
{
...
...
fs/minix/bitmap.c
View file @
f6506d68
...
...
@@ -112,14 +112,6 @@ int minix_new_block(struct super_block * sb)
if
(
j
<
sb
->
u
.
minix_sb
.
s_firstdatazone
||
j
>=
sb
->
u
.
minix_sb
.
s_nzones
)
return
0
;
if
(
!
(
bh
=
getblk
(
sb
->
s_dev
,
j
,
BLOCK_SIZE
)))
{
printk
(
"new_block: cannot get block"
);
return
0
;
}
memset
(
bh
->
b_data
,
0
,
BLOCK_SIZE
);
mark_buffer_uptodate
(
bh
,
1
);
mark_buffer_dirty
(
bh
,
1
);
brelse
(
bh
);
return
j
;
}
...
...
fs/minix/file.c
View file @
f6506d68
...
...
@@ -27,7 +27,51 @@
#include <linux/fs.h>
#include <linux/minix_fs.h>
static
ssize_t
minix_file_write
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
static
int
minix_writepage
(
struct
file
*
file
,
struct
page
*
page
)
{
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
unsigned
long
block
;
int
*
p
,
nr
[
PAGE_SIZE
/
BLOCK_SIZE
];
int
i
,
err
,
created
;
struct
buffer_head
*
bh
;
i
=
PAGE_SIZE
/
BLOCK_SIZE
;
block
=
page
->
offset
/
BLOCK_SIZE
;
p
=
nr
;
bh
=
page
->
buffers
;
do
{
if
(
bh
&&
bh
->
b_blocknr
)
*
p
=
bh
->
b_blocknr
;
else
*
p
=
minix_getblk_block
(
inode
,
block
,
1
,
&
err
,
&
created
);
if
(
!*
p
)
return
-
EIO
;
i
--
;
block
++
;
p
++
;
if
(
bh
)
bh
=
bh
->
b_this_page
;
}
while
(
i
>
0
);
/* IO start */
brw_page
(
WRITE
,
page
,
inode
->
i_dev
,
nr
,
BLOCK_SIZE
,
1
);
return
0
;
}
static
long
minix_write_one_page
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
bytes
,
const
char
*
buf
)
{
return
block_write_one_page
(
file
,
page
,
offset
,
bytes
,
buf
,
minix_getblk_block
);
}
/*
* Write to a file (through the page cache).
*/
static
ssize_t
minix_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
generic_file_write
(
file
,
buf
,
count
,
ppos
,
minix_write_one_page
);
}
/*
* We have mostly NULLs here: the current defaults are OK for
...
...
@@ -61,74 +105,12 @@ struct inode_operations minix_file_inode_operations = {
NULL
,
/* readlink */
NULL
,
/* follow_link */
generic_readpage
,
/* readpage */
NULL
,
/* writepage */
minix_writepage
,
/* writepage */
minix_bmap
,
/* bmap */
minix_truncate
,
/* truncate */
NULL
/* permission */
NULL
,
/* permission */
NULL
,
/* smap */
NULL
,
/* updatepage */
NULL
,
/* revalidate */
generic_block_flushpage
,
/* flushpage */
};
static
ssize_t
minix_file_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
inode
*
inode
=
filp
->
f_dentry
->
d_inode
;
off_t
pos
;
ssize_t
written
,
c
;
struct
buffer_head
*
bh
;
char
*
p
;
if
(
!
inode
)
{
printk
(
"minix_file_write: inode = NULL
\n
"
);
return
-
EINVAL
;
}
if
(
!
S_ISREG
(
inode
->
i_mode
))
{
printk
(
"minix_file_write: mode = %07o
\n
"
,
inode
->
i_mode
);
return
-
EINVAL
;
}
if
(
filp
->
f_flags
&
O_APPEND
)
pos
=
inode
->
i_size
;
else
pos
=
*
ppos
;
written
=
0
;
while
(
written
<
count
)
{
bh
=
minix_getblk
(
inode
,
pos
/
BLOCK_SIZE
,
1
);
if
(
!
bh
)
{
if
(
!
written
)
written
=
-
ENOSPC
;
break
;
}
c
=
BLOCK_SIZE
-
(
pos
%
BLOCK_SIZE
);
if
(
c
>
count
-
written
)
c
=
count
-
written
;
if
(
c
!=
BLOCK_SIZE
&&
!
buffer_uptodate
(
bh
))
{
ll_rw_block
(
READ
,
1
,
&
bh
);
wait_on_buffer
(
bh
);
if
(
!
buffer_uptodate
(
bh
))
{
brelse
(
bh
);
if
(
!
written
)
written
=
-
EIO
;
break
;
}
}
p
=
(
pos
%
BLOCK_SIZE
)
+
bh
->
b_data
;
c
-=
copy_from_user
(
p
,
buf
,
c
);
if
(
!
c
)
{
brelse
(
bh
);
if
(
!
written
)
written
=
-
EFAULT
;
break
;
}
update_vm_cache
(
inode
,
pos
,
p
,
c
);
mark_buffer_uptodate
(
bh
,
1
);
mark_buffer_dirty
(
bh
,
0
);
brelse
(
bh
);
pos
+=
c
;
written
+=
c
;
buf
+=
c
;
}
if
(
pos
>
inode
->
i_size
)
inode
->
i_size
=
pos
;
inode
->
i_mtime
=
inode
->
i_ctime
=
CURRENT_TIME
;
*
ppos
=
pos
;
mark_inode_dirty
(
inode
);
return
written
;
}
fs/minix/inode.c
View file @
f6506d68
This diff is collapsed.
Click to expand it.
fs/minix/truncate.c
View file @
f6506d68
...
...
@@ -32,6 +32,9 @@
* general case (size = XXX). I hope.
*/
#define DATA_BUFFER_USED(bh) \
((bh->b_count > 1) || buffer_locked(bh))
/*
* The functions for minix V1 fs truncation.
*/
...
...
@@ -52,7 +55,7 @@ static int V1_trunc_direct(struct inode * inode)
brelse
(
bh
);
goto
repeat
;
}
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
*
p
)
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
*
p
)
{
retry
=
1
;
brelse
(
bh
);
continue
;
...
...
@@ -103,7 +106,7 @@ static int V1_trunc_indirect(struct inode * inode, int offset, unsigned short *
brelse
(
bh
);
goto
repeat
;
}
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
*
ind
)
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
*
ind
)
{
retry
=
1
;
brelse
(
bh
);
continue
;
...
...
@@ -216,7 +219,7 @@ static int V2_trunc_direct(struct inode * inode)
brelse
(
bh
);
goto
repeat
;
}
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
*
p
)
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
*
p
)
{
retry
=
1
;
brelse
(
bh
);
continue
;
...
...
@@ -267,7 +270,7 @@ static int V2_trunc_indirect(struct inode * inode, int offset, unsigned long * p
brelse
(
bh
);
goto
repeat
;
}
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
*
ind
)
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
*
ind
)
{
retry
=
1
;
brelse
(
bh
);
continue
;
...
...
fs/nfs/dir.c
View file @
f6506d68
This diff is collapsed.
Click to expand it.
fs/nfs/inode.c
View file @
f6506d68
...
...
@@ -99,23 +99,28 @@ nfs_delete_inode(struct inode * inode)
int
failed
;
dprintk
(
"NFS: delete_inode(%x/%ld)
\n
"
,
inode
->
i_dev
,
inode
->
i_ino
);
/*
* Flush out any pending write requests ...
*/
if
(
NFS_WRITEBACK
(
inode
)
!=
NULL
)
{
unsigned
long
timeout
=
jiffies
+
5
*
HZ
;
if
(
S_ISDIR
(
inode
->
i_mode
))
{
nfs_free_dircache
(
inode
);
}
else
{
/*
* Flush out any pending write requests ...
*/
if
(
NFS_WRITEBACK
(
inode
)
!=
NULL
)
{
unsigned
long
timeout
=
jiffies
+
5
*
HZ
;
#ifdef NFS_DEBUG_VERBOSE
printk
(
"nfs_delete_inode: inode %ld has pending RPC requests
\n
"
,
inode
->
i_ino
);
#endif
nfs_inval
(
inode
);
while
(
NFS_WRITEBACK
(
inode
)
!=
NULL
&&
time_before
(
jiffies
,
timeout
))
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
HZ
/
10
);
nfs_inval
(
inode
);
while
(
NFS_WRITEBACK
(
inode
)
!=
NULL
&&
time_before
(
jiffies
,
timeout
))
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
HZ
/
10
);
}
current
->
state
=
TASK_RUNNING
;
if
(
NFS_WRITEBACK
(
inode
)
!=
NULL
)
printk
(
"NFS: Arghhh, stuck RPC requests!
\n
"
);
}
current
->
state
=
TASK_RUNNING
;
if
(
NFS_WRITEBACK
(
inode
)
!=
NULL
)
printk
(
"NFS: Arghhh, stuck RPC requests!
\n
"
);
}
failed
=
nfs_check_failed_request
(
inode
);
...
...
@@ -433,7 +438,7 @@ nfs_zap_caches(struct inode *inode)
invalidate_inode_pages
(
inode
);
if
(
S_ISDIR
(
inode
->
i_mode
))
nfs_
invalidate
_dircache
(
inode
);
nfs_
flush
_dircache
(
inode
);
}
/*
...
...
@@ -477,8 +482,6 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
inode
->
i_size
=
fattr
->
size
;
inode
->
i_mtime
=
fattr
->
mtime
.
seconds
;
NFS_OLDMTIME
(
inode
)
=
fattr
->
mtime
.
seconds
;
NFS_COOKIES
(
inode
)
=
NULL
;
NFS_WRITEBACK
(
inode
)
=
NULL
;
}
nfs_refresh_inode
(
inode
,
fattr
);
}
...
...
fs/pipe.c
View file @
f6506d68
...
...
@@ -102,9 +102,7 @@ static ssize_t pipe_write(struct file * filp, const char * buf,
free
=
count
;
else
free
=
1
;
/* can't do it atomically, wait for any free space */
up
(
&
inode
->
i_sem
);
if
(
down_interruptible
(
&
inode
->
i_atomic_write
))
{
down
(
&
inode
->
i_sem
);
if
(
down_interruptible
(
&
inode
->
i_sem
))
{
return
-
ERESTARTSYS
;
}
while
(
count
>
0
)
{
...
...
@@ -145,8 +143,7 @@ static ssize_t pipe_write(struct file * filp, const char * buf,
inode
->
i_ctime
=
inode
->
i_mtime
=
CURRENT_TIME
;
mark_inode_dirty
(
inode
);
errout:
up
(
&
inode
->
i_atomic_write
);
down
(
&
inode
->
i_sem
);
up
(
&
inode
->
i_sem
);
return
written
?
written
:
err
;
}
...
...
@@ -254,6 +251,7 @@ static int pipe_release(struct inode * inode)
inode
->
i_pipe
=
NULL
;
free_page
((
unsigned
long
)
info
->
base
);
kfree
(
info
);
return
0
;
}
wake_up_interruptible
(
&
PIPE_WAIT
(
*
inode
));
return
0
;
...
...
fs/read_write.c
View file @
f6506d68
...
...
@@ -166,9 +166,7 @@ asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count)
if
(
!
file
->
f_op
||
!
(
write
=
file
->
f_op
->
write
))
goto
out
;
down
(
&
inode
->
i_sem
);
ret
=
write
(
file
,
buf
,
count
,
&
file
->
f_pos
);
up
(
&
inode
->
i_sem
);
out:
fput
(
file
);
bad_file:
...
...
@@ -304,9 +302,7 @@ asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
if
(
!
file
)
goto
bad_file
;
if
(
file
->
f_op
&&
file
->
f_op
->
write
&&
(
file
->
f_mode
&
FMODE_WRITE
))
{
down
(
&
file
->
f_dentry
->
d_inode
->
i_sem
);
ret
=
do_readv_writev
(
VERIFY_READ
,
file
,
vector
,
count
);
up
(
&
file
->
f_dentry
->
d_inode
->
i_sem
);
}
fput
(
file
);
...
...
@@ -376,10 +372,7 @@ asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
if
(
pos
<
0
)
goto
out
;
down
(
&
file
->
f_dentry
->
d_inode
->
i_sem
);
ret
=
write
(
file
,
buf
,
count
,
&
pos
);
up
(
&
file
->
f_dentry
->
d_inode
->
i_sem
);
out:
fput
(
file
);
bad_file:
...
...
fs/sysv/file.c
View file @
f6506d68
...
...
@@ -33,7 +33,51 @@
#include <linux/fs.h>
#include <linux/sysv_fs.h>
static
ssize_t
sysv_file_write
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
static
int
sysv_writepage
(
struct
file
*
file
,
struct
page
*
page
)
{
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
unsigned
long
block
;
int
*
p
,
nr
[
PAGE_SIZE
/
512
];
int
i
,
err
,
created
;
struct
buffer_head
*
bh
;
i
=
PAGE_SIZE
>>
inode
->
i_sb
->
sv_block_size_bits
;
block
=
page
->
offset
>>
inode
->
i_sb
->
sv_block_size_bits
;
p
=
nr
;
bh
=
page
->
buffers
;
do
{
if
(
bh
&&
bh
->
b_blocknr
)
*
p
=
bh
->
b_blocknr
;
else
*
p
=
sysv_getblk_block
(
inode
,
block
,
1
,
&
err
,
&
created
);
if
(
!*
p
)
return
-
EIO
;
i
--
;
block
++
;
p
++
;
if
(
bh
)
bh
=
bh
->
b_this_page
;
}
while
(
i
>
0
);
/* IO start */
brw_page
(
WRITE
,
page
,
inode
->
i_dev
,
nr
,
inode
->
i_sb
->
sv_block_size
,
1
);
return
0
;
}
static
long
sysv_write_one_page
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
bytes
,
const
char
*
buf
)
{
return
block_write_one_page
(
file
,
page
,
offset
,
bytes
,
buf
,
sysv_getblk_block
);
}
/*
* Write to a file (through the page cache).
*/
static
ssize_t
sysv_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
generic_file_write
(
file
,
buf
,
count
,
ppos
,
sysv_write_one_page
);
}
/*
* We have mostly NULLs here: the current defaults are OK for
...
...
@@ -41,7 +85,7 @@ static ssize_t sysv_file_write(struct file *, const char *, size_t, loff_t *);
*/
static
struct
file_operations
sysv_file_operations
=
{
NULL
,
/* lseek - default */
sysv_file_read
,
/* read */
generic_file_read
,
/* read */
sysv_file_write
,
/* write */
NULL
,
/* readdir - bad */
NULL
,
/* poll - default */
...
...
@@ -50,7 +94,10 @@ static struct file_operations sysv_file_operations = {
NULL
,
/* no special open is needed */
NULL
,
/* flush */
NULL
,
/* release */
sysv_sync_file
/* fsync */
sysv_sync_file
,
/* fsync */
NULL
,
/* fasync */
NULL
,
/* check_media_change */
NULL
/* revalidate */
};
struct
inode_operations
sysv_file_inode_operations
=
{
...
...
@@ -67,208 +114,12 @@ struct inode_operations sysv_file_inode_operations = {
NULL
,
/* readlink */
NULL
,
/* follow_link */
generic_readpage
,
/* readpage */
NULL
,
/* writepage */
sysv_writepage
,
/* writepage */
sysv_bmap
,
/* bmap */
sysv_truncate
,
/* truncate */
NULL
/* permission */
NULL
,
/* permission */
NULL
,
/* smap */
NULL
,
/* updatepage */
NULL
,
/* revalidate */
generic_block_flushpage
,
/* flushpage */
};
ssize_t
sysv_file_read
(
struct
file
*
filp
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
inode
*
inode
=
filp
->
f_dentry
->
d_inode
;
struct
super_block
*
sb
=
inode
->
i_sb
;
ssize_t
read
,
left
,
chars
;
size_t
block
;
ssize_t
blocks
,
offset
;
int
bhrequest
,
uptodate
;
struct
buffer_head
**
bhb
,
**
bhe
;
struct
buffer_head
*
bhreq
[
NBUF
];
struct
buffer_head
*
buflist
[
NBUF
];
size_t
size
;
if
(
!
inode
)
{
printk
(
"sysv_file_read: inode = NULL
\n
"
);
return
-
EINVAL
;
}
if
(
!
S_ISREG
(
inode
->
i_mode
))
{
printk
(
"sysv_file_read: mode = %07o
\n
"
,
inode
->
i_mode
);
return
-
EINVAL
;
}
offset
=
*
ppos
;
size
=
inode
->
i_size
;
if
(
offset
>
size
)
left
=
0
;
else
left
=
size
-
offset
;
if
(
left
>
count
)
left
=
count
;
if
(
left
<=
0
)
return
0
;
read
=
0
;
block
=
offset
>>
sb
->
sv_block_size_bits
;
offset
&=
sb
->
sv_block_size_1
;
size
=
(
size
+
sb
->
sv_block_size_1
)
>>
sb
->
sv_block_size_bits
;
blocks
=
(
left
+
offset
+
sb
->
sv_block_size_1
)
>>
sb
->
sv_block_size_bits
;
bhb
=
bhe
=
buflist
;
if
(
filp
->
f_reada
)
{
blocks
+=
read_ahead
[
MAJOR
(
inode
->
i_dev
)]
>>
(
sb
->
sv_block_size_bits
-
9
);
if
(
block
+
blocks
>
size
)
blocks
=
size
-
block
;
}
/* We do this in a two stage process. We first try to request
as many blocks as we can, then we wait for the first one to
complete, and then we try to wrap up as many as are actually
done. This routine is rather generic, in that it can be used
in a filesystem by substituting the appropriate function in
for getblk.
This routine is optimized to make maximum use of the various
buffers and caches.
*/
do
{
bhrequest
=
0
;
uptodate
=
1
;
while
(
blocks
)
{
--
blocks
;
*
bhb
=
sysv_getblk
(
inode
,
block
++
,
0
);
if
(
*
bhb
&&
!
buffer_uptodate
(
*
bhb
))
{
uptodate
=
0
;
bhreq
[
bhrequest
++
]
=
*
bhb
;
}
if
(
++
bhb
==
&
buflist
[
NBUF
])
bhb
=
buflist
;
/* If the block we have on hand is uptodate, go ahead
and complete processing. */
if
(
uptodate
)
break
;
if
(
bhb
==
bhe
)
break
;
}
/* Now request them all */
if
(
bhrequest
)
ll_rw_block
(
READ
,
bhrequest
,
bhreq
);
do
{
/* Finish off all I/O that has actually completed */
if
(
*
bhe
)
{
wait_on_buffer
(
*
bhe
);
if
(
!
buffer_uptodate
(
*
bhe
))
{
/* read error? */
brelse
(
*
bhe
);
if
(
++
bhe
==
&
buflist
[
NBUF
])
bhe
=
buflist
;
left
=
0
;
break
;
}
}
if
(
left
<
sb
->
sv_block_size
-
offset
)
chars
=
left
;
else
chars
=
sb
->
sv_block_size
-
offset
;
*
ppos
+=
chars
;
left
-=
chars
;
read
+=
chars
;
if
(
*
bhe
)
{
copy_to_user
(
buf
,
offset
+
(
*
bhe
)
->
b_data
,
chars
);
brelse
(
*
bhe
);
buf
+=
chars
;
}
else
{
while
(
chars
--
>
0
)
put_user
(
0
,
buf
++
);
}
offset
=
0
;
if
(
++
bhe
==
&
buflist
[
NBUF
])
bhe
=
buflist
;
}
while
(
left
>
0
&&
bhe
!=
bhb
&&
(
!*
bhe
||
!
buffer_locked
(
*
bhe
)));
}
while
(
left
>
0
);
/* Release the read-ahead blocks */
while
(
bhe
!=
bhb
)
{
brelse
(
*
bhe
);
if
(
++
bhe
==
&
buflist
[
NBUF
])
bhe
=
buflist
;
};
if
(
!
read
)
return
-
EIO
;
filp
->
f_reada
=
1
;
if
(
!
IS_RDONLY
(
inode
))
{
inode
->
i_atime
=
CURRENT_TIME
;
mark_inode_dirty
(
inode
);
}
return
read
;
}
static
ssize_t
sysv_file_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
inode
*
inode
=
filp
->
f_dentry
->
d_inode
;
struct
super_block
*
sb
=
inode
->
i_sb
;
off_t
pos
;
ssize_t
written
,
c
;
struct
buffer_head
*
bh
;
char
*
p
;
if
(
!
inode
)
{
printk
(
"sysv_file_write: inode = NULL
\n
"
);
return
-
EINVAL
;
}
if
(
!
S_ISREG
(
inode
->
i_mode
))
{
printk
(
"sysv_file_write: mode = %07o
\n
"
,
inode
->
i_mode
);
return
-
EINVAL
;
}
/*
* OK, append may not work when many processes are writing at the same time
* but so what. That way leads to madness anyway.
* But we need to protect against simultaneous truncate as we may end up
* writing our data into blocks that have meanwhile been incorporated into
* the freelist, thereby trashing the freelist.
*/
if
(
filp
->
f_flags
&
O_APPEND
)
pos
=
inode
->
i_size
;
else
pos
=
*
ppos
;
written
=
0
;
while
(
written
<
count
)
{
bh
=
sysv_getblk
(
inode
,
pos
>>
sb
->
sv_block_size_bits
,
1
);
if
(
!
bh
)
{
if
(
!
written
)
written
=
-
ENOSPC
;
break
;
}
c
=
sb
->
sv_block_size
-
(
pos
&
sb
->
sv_block_size_1
);
if
(
c
>
count
-
written
)
c
=
count
-
written
;
if
(
c
!=
sb
->
sv_block_size
&&
!
buffer_uptodate
(
bh
))
{
ll_rw_block
(
READ
,
1
,
&
bh
);
wait_on_buffer
(
bh
);
if
(
!
buffer_uptodate
(
bh
))
{
brelse
(
bh
);
if
(
!
written
)
written
=
-
EIO
;
break
;
}
}
/* now either c==sb->sv_block_size or buffer_uptodate(bh) */
p
=
(
pos
&
sb
->
sv_block_size_1
)
+
bh
->
b_data
;
copy_from_user
(
p
,
buf
,
c
);
update_vm_cache
(
inode
,
pos
,
p
,
c
);
pos
+=
c
;
if
(
pos
>
inode
->
i_size
)
{
inode
->
i_size
=
pos
;
mark_inode_dirty
(
inode
);
}
written
+=
c
;
buf
+=
c
;
mark_buffer_uptodate
(
bh
,
1
);
mark_buffer_dirty
(
bh
,
0
);
brelse
(
bh
);
}
inode
->
i_mtime
=
inode
->
i_ctime
=
CURRENT_TIME
;
*
ppos
=
pos
;
mark_inode_dirty
(
inode
);
return
written
;
}
fs/sysv/inode.c
View file @
f6506d68
...
...
@@ -657,7 +657,8 @@ int sysv_bmap(struct inode * inode,int block_nr)
/* Access selected blocks of regular files (or directories) */
static
struct
buffer_head
*
inode_getblk
(
struct
inode
*
inode
,
int
nr
,
int
create
)
static
struct
buffer_head
*
inode_getblk
(
struct
inode
*
inode
,
int
nr
,
int
create
,
int
metadata
,
int
*
phys_block
,
int
*
created
)
{
struct
super_block
*
sb
;
u32
tmp
;
...
...
@@ -669,31 +670,48 @@ static struct buffer_head * inode_getblk(struct inode * inode, int nr, int creat
repeat:
tmp
=
*
p
;
if
(
tmp
)
{
result
=
sv_getblk
(
sb
,
inode
->
i_dev
,
tmp
);
if
(
tmp
==
*
p
)
return
result
;
brelse
(
result
);
goto
repeat
;
if
(
metadata
)
{
result
=
sv_getblk
(
sb
,
inode
->
i_dev
,
tmp
);
if
(
tmp
==
*
p
)
return
result
;
brelse
(
result
);
goto
repeat
;
}
else
{
*
phys_block
=
tmp
;
return
NULL
;
}
}
if
(
!
create
)
return
NULL
;
tmp
=
sysv_new_block
(
sb
);
if
(
!
tmp
)
return
NULL
;
result
=
sv_getblk
(
sb
,
inode
->
i_dev
,
tmp
);
if
(
*
p
)
{
sysv_free_block
(
sb
,
tmp
);
brelse
(
result
);
goto
repeat
;
if
(
metadata
)
{
result
=
sv_getblk
(
sb
,
inode
->
i_dev
,
tmp
);
if
(
*
p
)
{
sysv_free_block
(
sb
,
tmp
);
brelse
(
result
);
goto
repeat
;
}
}
else
{
if
(
*
p
)
{
sysv_free_block
(
sb
,
tmp
);
goto
repeat
;
}
*
phys_block
=
tmp
;
result
=
NULL
;
*
created
=
1
;
}
*
p
=
tmp
;
inode
->
i_ctime
=
CURRENT_TIME
;
mark_inode_dirty
(
inode
);
return
result
;
}
static
struct
buffer_head
*
block_getblk
(
struct
inode
*
inode
,
struct
buffer_head
*
bh
,
int
nr
,
int
create
)
struct
buffer_head
*
bh
,
int
nr
,
int
create
,
int
metadata
,
int
*
phys_block
,
int
*
created
)
{
struct
super_block
*
sb
;
u32
tmp
,
block
;
...
...
@@ -717,13 +735,19 @@ static struct buffer_head * block_getblk(struct inode * inode,
if
(
sb
->
sv_convert
)
block
=
from_coh_ulong
(
block
);
if
(
tmp
)
{
result
=
sv_getblk
(
sb
,
bh
->
b_dev
,
block
);
if
(
tmp
==
*
p
)
{
if
(
metadata
)
{
result
=
sv_getblk
(
sb
,
bh
->
b_dev
,
block
);
if
(
tmp
==
*
p
)
{
brelse
(
bh
);
return
result
;
}
brelse
(
result
);
goto
repeat
;
}
else
{
*
phys_block
=
tmp
;
brelse
(
bh
);
return
result
;
return
NULL
;
}
brelse
(
result
);
goto
repeat
;
}
if
(
!
create
)
{
brelse
(
bh
);
...
...
@@ -734,11 +758,17 @@ static struct buffer_head * block_getblk(struct inode * inode,
brelse
(
bh
);
return
NULL
;
}
result
=
sv_getblk
(
sb
,
bh
->
b_dev
,
block
);
if
(
*
p
)
{
sysv_free_block
(
sb
,
block
);
brelse
(
result
);
goto
repeat
;
if
(
metadata
)
{
result
=
sv_getblk
(
sb
,
bh
->
b_dev
,
block
);
if
(
*
p
)
{
sysv_free_block
(
sb
,
block
);
brelse
(
result
);
goto
repeat
;
}
}
else
{
*
phys_block
=
tmp
;
result
=
NULL
;
*
created
=
1
;
}
*
p
=
(
sb
->
sv_convert
?
to_coh_ulong
(
block
)
:
block
);
mark_buffer_dirty
(
bh
,
1
);
...
...
@@ -746,37 +776,74 @@ static struct buffer_head * block_getblk(struct inode * inode,
return
result
;
}
struct
buffer_head
*
sysv_getblk
(
struct
inode
*
inode
,
unsigned
int
block
,
int
create
)
int
sysv_getblk_block
(
struct
inode
*
inode
,
long
block
,
int
create
,
int
*
err
,
int
*
created
)
{
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
buffer_head
*
bh
;
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
buffer_head
*
bh
,
*
tmp
;
int
phys_block
;
if
(
block
<
10
)
return
inode_getblk
(
inode
,
block
,
create
);
*
err
=
-
EIO
;
if
(
block
<
0
)
{
printk
(
"sysv_getblk: block<0"
);
return
0
;
}
if
(
block
>
sb
->
sv_ind_per_block_3
)
{
printk
(
"sysv_getblk: block>big"
);
return
0
;
}
if
(
block
<
10
)
{
tmp
=
inode_getblk
(
inode
,
block
,
create
,
0
,
&
phys_block
,
created
);
goto
out
;
}
block
-=
10
;
if
(
block
<
sb
->
sv_ind_per_block
)
{
bh
=
inode_getblk
(
inode
,
10
,
create
);
return
block_getblk
(
inode
,
bh
,
block
,
create
);
bh
=
inode_getblk
(
inode
,
10
,
create
,
1
,
NULL
,
NULL
);
tmp
=
block_getblk
(
inode
,
bh
,
block
,
create
,
0
,
&
phys_block
,
created
);
goto
out
;
}
block
-=
sb
->
sv_ind_per_block
;
if
(
block
<
sb
->
sv_ind_per_block_2
)
{
bh
=
inode_getblk
(
inode
,
11
,
create
);
bh
=
block_getblk
(
inode
,
bh
,
block
>>
sb
->
sv_ind_per_block_bits
,
create
);
return
block_getblk
(
inode
,
bh
,
block
&
sb
->
sv_ind_per_block_1
,
create
);
bh
=
inode_getblk
(
inode
,
11
,
create
,
1
,
NULL
,
NULL
);
bh
=
block_getblk
(
inode
,
bh
,
block
>>
sb
->
sv_ind_per_block_bits
,
create
,
1
,
NULL
,
NULL
);
tmp
=
block_getblk
(
inode
,
bh
,
block
&
sb
->
sv_ind_per_block_1
,
create
,
0
,
&
phys_block
,
created
);
goto
out
;
}
block
-=
sb
->
sv_ind_per_block_2
;
if
(
block
<
sb
->
sv_ind_per_block_3
)
{
bh
=
inode_getblk
(
inode
,
12
,
create
);
bh
=
block_getblk
(
inode
,
bh
,
block
>>
sb
->
sv_ind_per_block_2_bits
,
create
);
bh
=
block_getblk
(
inode
,
bh
,
(
block
>>
sb
->
sv_ind_per_block_bits
)
&
sb
->
sv_ind_per_block_1
,
create
);
return
block_getblk
(
inode
,
bh
,
block
&
sb
->
sv_ind_per_block_1
,
create
);
}
if
((
int
)
block
<
0
)
{
printk
(
"sysv_getblk: block<0"
);
return
NULL
;
bh
=
inode_getblk
(
inode
,
12
,
create
,
1
,
NULL
,
NULL
);
bh
=
block_getblk
(
inode
,
bh
,
block
>>
sb
->
sv_ind_per_block_2_bits
,
create
,
1
,
NULL
,
NULL
);
bh
=
block_getblk
(
inode
,
bh
,
(
block
>>
sb
->
sv_ind_per_block_bits
)
&
sb
->
sv_ind_per_block_1
,
create
,
1
,
NULL
,
NULL
);
tmp
=
block_getblk
(
inode
,
bh
,
block
&
sb
->
sv_ind_per_block_1
,
create
,
0
,
&
phys_block
,
created
);
out:
*
err
=
0
;
return
phys_block
;
}
struct
buffer_head
*
sysv_getblk
(
struct
inode
*
inode
,
unsigned
int
block
,
int
create
)
{
struct
buffer_head
*
tmp
=
NULL
;
int
phys_block
;
int
err
,
created
;
phys_block
=
sysv_getblk_block
(
inode
,
block
,
create
,
&
err
,
&
created
);
if
(
phys_block
)
{
tmp
=
getblk
(
inode
->
i_dev
,
phys_block
,
BLOCK_SIZE
);
if
(
created
)
{
memset
(
tmp
->
b_data
,
0
,
BLOCK_SIZE
);
mark_buffer_uptodate
(
tmp
,
1
);
mark_buffer_dirty
(
tmp
,
1
);
}
}
printk
(
"sysv_getblk: block>big"
);
return
NULL
;
return
tmp
;
}
struct
buffer_head
*
sysv_file_bread
(
struct
inode
*
inode
,
int
block
,
int
create
)
...
...
fs/sysv/truncate.c
View file @
f6506d68
...
...
@@ -35,6 +35,9 @@
* general case (size = XXX). I hope.
*/
#define DATA_BUFFER_USED(bh) \
((bh->b_count > 1) || buffer_locked(bh))
/* We throw away any data beyond inode->i_size. */
static
int
trunc_direct
(
struct
inode
*
inode
)
...
...
@@ -58,7 +61,7 @@ static int trunc_direct(struct inode * inode)
brelse
(
bh
);
goto
repeat
;
}
if
((
bh
&&
bh
->
b_count
!=
1
)
||
(
block
!=
*
p
))
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
(
block
!=
*
p
))
{
retry
=
1
;
brelse
(
bh
);
continue
;
...
...
@@ -115,7 +118,7 @@ static int trunc_indirect(struct inode * inode, unsigned long offset, sysv_zone_
brelse
(
bh
);
goto
repeat
;
}
if
((
bh
&&
bh
->
b_count
!=
1
)
||
(
tmp
!=
*
ind
))
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
(
tmp
!=
*
ind
))
{
retry
=
1
;
brelse
(
bh
);
continue
;
...
...
@@ -128,7 +131,7 @@ static int trunc_indirect(struct inode * inode, unsigned long offset, sysv_zone_
for
(
i
=
0
;
i
<
sb
->
sv_ind_per_block
;
i
++
)
if
(((
sysv_zone_t
*
)
indbh
->
b_data
)[
i
])
goto
done
;
if
(
(
indbh
->
b_count
!=
1
)
||
(
indtmp
!=
*
p
))
{
if
(
DATA_BUFFER_USED
(
indbh
)
||
(
indtmp
!=
*
p
))
{
brelse
(
indbh
);
return
1
;
}
...
...
@@ -185,7 +188,7 @@ static int trunc_dindirect(struct inode * inode, unsigned long offset, sysv_zone
for
(
i
=
0
;
i
<
sb
->
sv_ind_per_block
;
i
++
)
if
(((
sysv_zone_t
*
)
indbh
->
b_data
)[
i
])
goto
done
;
if
(
(
indbh
->
b_count
!=
1
)
||
(
indtmp
!=
*
p
))
{
if
(
DATA_BUFFER_USED
(
indbh
)
||
(
indtmp
!=
*
p
))
{
brelse
(
indbh
);
return
1
;
}
...
...
@@ -242,7 +245,7 @@ static int trunc_tindirect(struct inode * inode, unsigned long offset, sysv_zone
for
(
i
=
0
;
i
<
sb
->
sv_ind_per_block
;
i
++
)
if
(((
sysv_zone_t
*
)
indbh
->
b_data
)[
i
])
goto
done
;
if
(
(
indbh
->
b_count
!=
1
)
||
(
indtmp
!=
*
p
))
{
if
(
DATA_BUFFER_USED
(
indbh
)
||
(
indtmp
!=
*
p
))
{
brelse
(
indbh
);
return
1
;
}
...
...
fs/ufs/file.c
View file @
f6506d68
...
...
@@ -41,52 +41,6 @@
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
static
long
long
ufs_file_lseek
(
struct
file
*
,
long
long
,
int
);
static
ssize_t
ufs_file_write
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
static
int
ufs_release_file
(
struct
inode
*
,
struct
file
*
);
/*
* We have mostly NULL's here: the current defaults are ok for
* the ufs filesystem.
*/
static
struct
file_operations
ufs_file_operations
=
{
ufs_file_lseek
,
/* lseek */
generic_file_read
,
/* read */
ufs_file_write
,
/* write */
NULL
,
/* readdir - bad */
NULL
,
/* poll - default */
NULL
,
/* ioctl */
generic_file_mmap
,
/* mmap */
NULL
,
/* no special open is needed */
NULL
,
/* flush */
ufs_release_file
,
/* release */
NULL
,
/* fsync */
NULL
,
/* fasync */
NULL
,
/* check_media_change */
NULL
/* revalidate */
};
struct
inode_operations
ufs_file_inode_operations
=
{
&
ufs_file_operations
,
/* default file operations */
NULL
,
/* create */
NULL
,
/* lookup */
NULL
,
/* link */
NULL
,
/* unlink */
NULL
,
/* symlink */
NULL
,
/* mkdir */
NULL
,
/* rmdir */
NULL
,
/* mknod */
NULL
,
/* rename */
NULL
,
/* readlink */
NULL
,
/* follow_link */
generic_readpage
,
/* readpage */
NULL
,
/* writepage */
ufs_bmap
,
/* bmap */
ufs_truncate
,
/* truncate */
NULL
,
/* permission */
NULL
/* smap */
};
/*
* Make sure the offset never goes beyond the 32-bit mark..
*/
...
...
@@ -133,139 +87,49 @@ static inline void remove_suid(struct inode *inode)
}
}
static
ssize_t
ufs_file_write
(
struct
file
*
filp
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
int
ufs_writepage
(
struct
file
*
file
,
struct
page
*
page
)
{
struct
inode
*
inode
=
filp
->
f_dentry
->
d_inode
;
__u32
pos
;
long
block
;
int
offset
;
int
written
,
c
;
struct
buffer_head
*
bh
,
*
bufferlist
[
NBUF
];
struct
super_block
*
sb
;
int
err
;
int
i
,
buffercount
,
write_error
;
/* POSIX: mtime/ctime may not change for 0 count */
if
(
!
count
)
return
0
;
write_error
=
buffercount
=
0
;
if
(
!
inode
)
return
-
EINVAL
;
sb
=
inode
->
i_sb
;
if
(
sb
->
s_flags
&
MS_RDONLY
)
/*
* This fs has been automatically remounted ro because of errors
*/
return
-
ENOSPC
;
if
(
!
S_ISREG
(
inode
->
i_mode
))
{
ufs_warning
(
sb
,
"ufs_file_write"
,
"mode = %07o"
,
inode
->
i_mode
);
return
-
EINVAL
;
}
remove_suid
(
inode
);
if
(
filp
->
f_flags
&
O_APPEND
)
pos
=
inode
->
i_size
;
else
{
pos
=
*
ppos
;
if
(
pos
!=
*
ppos
)
return
-
EINVAL
;
}
/* Check for overflow.. */
if
(
pos
>
(
__u32
)
(
pos
+
count
))
{
count
=
~
pos
;
/* == 0xFFFFFFFF - pos */
if
(
!
count
)
return
-
EFBIG
;
}
/*
* If a file has been opened in synchronous mode, we have to ensure
* that meta-data will also be written synchronously. Thus, we
* set the i_osync field. This field is tested by the allocation
* routines.
*/
if
(
filp
->
f_flags
&
O_SYNC
)
inode
->
u
.
ufs_i
.
i_osync
++
;
block
=
pos
>>
sb
->
s_blocksize_bits
;
offset
=
pos
&
(
sb
->
s_blocksize
-
1
);
c
=
sb
->
s_blocksize
-
offset
;
written
=
0
;
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
unsigned
long
block
;
int
*
p
,
nr
[
PAGE_SIZE
/
512
];
int
i
,
err
,
created
;
struct
buffer_head
*
bh
;
i
=
PAGE_SIZE
>>
inode
->
i_sb
->
s_blocksize_bits
;
block
=
page
->
offset
>>
inode
->
i_sb
->
s_blocksize_bits
;
p
=
nr
;
bh
=
page
->
buffers
;
do
{
bh
=
ufs_getfrag
(
inode
,
block
,
1
,
&
err
);
if
(
!
bh
)
{
if
(
!
written
)
written
=
err
;
break
;
}
if
(
c
>
count
)
c
=
count
;
if
(
c
!=
sb
->
s_blocksize
&&
!
buffer_uptodate
(
bh
))
{
ll_rw_block
(
READ
,
1
,
&
bh
);
wait_on_buffer
(
bh
);
if
(
!
buffer_uptodate
(
bh
))
{
brelse
(
bh
);
if
(
!
written
)
written
=
-
EIO
;
break
;
}
}
c
-=
copy_from_user
(
bh
->
b_data
+
offset
,
buf
,
c
);
if
(
!
c
)
{
brelse
(
bh
);
if
(
!
written
)
written
=
-
EFAULT
;
break
;
}
update_vm_cache
(
inode
,
pos
,
bh
->
b_data
+
offset
,
c
);
pos
+=
c
;
written
+=
c
;
buf
+=
c
;
count
-=
c
;
mark_buffer_uptodate
(
bh
,
1
);
mark_buffer_dirty
(
bh
,
0
);
if
(
filp
->
f_flags
&
O_SYNC
)
bufferlist
[
buffercount
++
]
=
bh
;
if
(
bh
&&
bh
->
b_blocknr
)
*
p
=
bh
->
b_blocknr
;
else
brelse
(
bh
);
if
(
buffercount
==
NBUF
){
ll_rw_block
(
WRITE
,
buffercount
,
bufferlist
);
for
(
i
=
0
;
i
<
buffercount
;
i
++
){
wait_on_buffer
(
bufferlist
[
i
]);
if
(
!
buffer_uptodate
(
bufferlist
[
i
]))
write_error
=
1
;
brelse
(
bufferlist
[
i
]);
}
buffercount
=
0
;
}
if
(
write_error
)
break
;
*
p
=
ufs_getfrag_block
(
inode
,
block
,
1
,
&
err
,
&
created
);
if
(
!*
p
)
return
-
EIO
;
i
--
;
block
++
;
offset
=
0
;
c
=
sb
->
s_blocksize
;
}
while
(
count
);
if
(
buffercount
){
ll_rw_block
(
WRITE
,
buffercount
,
bufferlist
);
for
(
i
=
0
;
i
<
buffercount
;
i
++
){
wait_on_buffer
(
bufferlist
[
i
]);
if
(
!
buffer_uptodate
(
bufferlist
[
i
]))
write_error
=
1
;
brelse
(
bufferlist
[
i
]);
}
}
if
(
pos
>
inode
->
i_size
)
inode
->
i_size
=
pos
;
if
(
filp
->
f_flags
&
O_SYNC
)
inode
->
u
.
ufs_i
.
i_osync
--
;
inode
->
i_ctime
=
inode
->
i_mtime
=
CURRENT_TIME
;
*
ppos
=
pos
;
mark_inode_dirty
(
inode
);
return
written
;
p
++
;
if
(
bh
)
bh
=
bh
->
b_this_page
;
}
while
(
i
>
0
);
brw_page
(
WRITE
,
page
,
inode
->
i_dev
,
nr
,
inode
->
i_sb
->
s_blocksize
,
1
);
return
0
;
}
static
long
ufs_write_one_page
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
bytes
,
const
char
*
buf
)
{
return
block_write_one_page
(
file
,
page
,
offset
,
bytes
,
buf
,
ufs_getfrag_block
);
}
/*
* Write to a file (through the page cache).
*/
static
ssize_t
ufs_file_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
generic_file_write
(
file
,
buf
,
count
,
ppos
,
ufs_write_one_page
);
}
/*
...
...
@@ -277,3 +141,48 @@ static int ufs_release_file (struct inode * inode, struct file * filp)
{
return
0
;
}
/*
* We have mostly NULL's here: the current defaults are ok for
* the ufs filesystem.
*/
static
struct
file_operations
ufs_file_operations
=
{
ufs_file_lseek
,
/* lseek */
generic_file_read
,
/* read */
ufs_file_write
,
/* write */
NULL
,
/* readdir - bad */
NULL
,
/* poll - default */
NULL
,
/* ioctl */
generic_file_mmap
,
/* mmap */
NULL
,
/* no special open is needed */
NULL
,
/* flush */
ufs_release_file
,
/* release */
NULL
,
/* fsync */
NULL
,
/* fasync */
NULL
,
/* check_media_change */
NULL
/* revalidate */
};
struct
inode_operations
ufs_file_inode_operations
=
{
&
ufs_file_operations
,
/* default file operations */
NULL
,
/* create */
NULL
,
/* lookup */
NULL
,
/* link */
NULL
,
/* unlink */
NULL
,
/* symlink */
NULL
,
/* mkdir */
NULL
,
/* rmdir */
NULL
,
/* mknod */
NULL
,
/* rename */
NULL
,
/* readlink */
NULL
,
/* follow_link */
generic_readpage
,
/* readpage */
ufs_writepage
,
/* writepage */
ufs_bmap
,
/* bmap */
ufs_truncate
,
/* truncate */
NULL
,
/* permission */
NULL
,
/* smap */
NULL
,
/* updatepage */
NULL
,
/* revalidate */
generic_block_flushpage
,
/* flushpage */
};
fs/ufs/inode.c
View file @
f6506d68
...
...
@@ -175,7 +175,7 @@ int ufs_bmap (struct inode * inode, int fragment)
static
struct
buffer_head
*
ufs_inode_getfrag
(
struct
inode
*
inode
,
unsigned
fragment
,
unsigned
new_fragment
,
int
create
,
unsigned
required
,
int
*
err
)
unsigned
required
,
int
*
err
,
int
metadata
,
int
*
phys_block
,
int
*
created
)
{
struct
super_block
*
sb
;
struct
ufs_sb_private_info
*
uspi
;
...
...
@@ -201,13 +201,19 @@ static struct buffer_head * ufs_inode_getfrag (struct inode * inode,
tmp
=
SWAB32
(
*
p
);
lastfrag
=
inode
->
u
.
ufs_i
.
i_lastfrag
;
if
(
tmp
&&
fragment
<
lastfrag
)
{
result
=
getblk
(
sb
->
s_dev
,
uspi
->
s_sbbase
+
tmp
+
blockoff
,
sb
->
s_blocksize
);
if
(
tmp
==
SWAB32
(
*
p
))
{
UFSD
((
"EXIT, result %u
\n
"
,
tmp
+
blockoff
))
return
result
;
if
(
metadata
)
{
result
=
getblk
(
sb
->
s_dev
,
uspi
->
s_sbbase
+
tmp
+
blockoff
,
sb
->
s_blocksize
);
if
(
tmp
==
SWAB32
(
*
p
))
{
UFSD
((
"EXIT, result %u
\n
"
,
tmp
+
blockoff
))
return
result
;
}
brelse
(
result
);
goto
repeat
;
}
else
{
*
phys_block
=
tmp
;
return
NULL
;
}
brelse
(
result
);
goto
repeat
;
}
*
err
=
-
EFBIG
;
if
(
!
create
)
...
...
@@ -269,7 +275,20 @@ static struct buffer_head * ufs_inode_getfrag (struct inode * inode,
else
return
NULL
;
}
result
=
getblk
(
inode
->
i_dev
,
tmp
+
blockoff
,
sb
->
s_blocksize
);
/* The nullification of framgents done in ufs/balloc.c is
* something I don't have the stomache to move into here right
* now. -DaveM
*/
if
(
metadata
)
{
result
=
getblk
(
inode
->
i_dev
,
tmp
+
blockoff
,
sb
->
s_blocksize
);
}
else
{
*
phys_block
=
tmp
;
result
=
NULL
;
*
err
=
0
;
*
created
=
1
;
}
inode
->
i_ctime
=
CURRENT_TIME
;
if
(
IS_SYNC
(
inode
))
ufs_sync_inode
(
inode
);
...
...
@@ -280,7 +299,7 @@ static struct buffer_head * ufs_inode_getfrag (struct inode * inode,
static
struct
buffer_head
*
ufs_block_getfrag
(
struct
inode
*
inode
,
struct
buffer_head
*
bh
,
unsigned
fragment
,
unsigned
new_fragment
,
int
create
,
unsigned
blocksize
,
int
*
err
)
int
create
,
unsigned
blocksize
,
int
*
err
,
int
metadata
,
int
*
phys_block
,
int
*
created
)
{
struct
super_block
*
sb
;
struct
ufs_sb_private_info
*
uspi
;
...
...
@@ -312,19 +331,36 @@ static struct buffer_head * ufs_block_getfrag (struct inode * inode,
repeat:
tmp
=
SWAB32
(
*
p
);
if
(
tmp
)
{
result
=
getblk
(
bh
->
b_dev
,
uspi
->
s_sbbase
+
tmp
+
blockoff
,
sb
->
s_blocksize
);
if
(
tmp
==
SWAB32
(
*
p
))
{
if
(
metadata
)
{
result
=
getblk
(
bh
->
b_dev
,
uspi
->
s_sbbase
+
tmp
+
blockoff
,
sb
->
s_blocksize
);
if
(
tmp
==
SWAB32
(
*
p
))
{
brelse
(
bh
);
UFSD
((
"EXIT, result %u
\n
"
,
tmp
+
blockoff
))
return
result
;
}
brelse
(
result
);
goto
repeat
;
}
else
{
*
phys_block
=
tmp
;
brelse
(
bh
);
UFSD
((
"EXIT, result %u
\n
"
,
tmp
+
blockoff
))
return
result
;
return
NULL
;
}
brelse
(
result
);
goto
repeat
;
}
if
(
!
create
||
new_fragment
>=
(
current
->
rlim
[
RLIMIT_FSIZE
].
rlim_cur
>>
sb
->
s_blocksize
))
{
*
err
=
-
EFBIG
;
if
(
!
create
)
{
brelse
(
bh
);
*
err
=
-
EFBIG
;
return
NULL
;
}
else
{
unsigned
long
limit
=
current
->
rlim
[
RLIMIT_FSIZE
].
rlim_cur
;
if
(
limit
<
RLIM_INFINITY
)
{
limit
>>=
sb
->
s_blocksize_bits
;
if
(
new_fragment
>=
limit
)
{
brelse
(
bh
);
send_sig
(
SIGXFSZ
,
current
,
0
);
return
NULL
;
}
}
}
if
(
block
&&
(
tmp
=
SWAB32
(((
u32
*
)
bh
->
b_data
)[
block
-
1
])
+
uspi
->
s_fpb
))
goal
=
tmp
+
uspi
->
s_fpb
;
...
...
@@ -334,12 +370,25 @@ static struct buffer_head * ufs_block_getfrag (struct inode * inode,
if
(
!
tmp
)
{
if
(
SWAB32
(
*
p
))
{
goto
repeat
;
}
else
{
}
else
{
brelse
(
bh
);
return
NULL
;
}
}
result
=
getblk
(
bh
->
b_dev
,
tmp
+
blockoff
,
sb
->
s_blocksize
);
/* The nullification of framgents done in ufs/balloc.c is
* something I don't have the stomache to move into here right
* now. -DaveM
*/
if
(
metadata
)
{
result
=
getblk
(
bh
->
b_dev
,
tmp
+
blockoff
,
sb
->
s_blocksize
);
}
else
{
*
phys_block
=
tmp
;
result
=
NULL
;
*
err
=
0
;
*
created
=
1
;
}
mark_buffer_dirty
(
bh
,
1
);
if
(
IS_SYNC
(
inode
))
{
ll_rw_block
(
WRITE
,
1
,
&
bh
);
...
...
@@ -352,14 +401,15 @@ static struct buffer_head * ufs_block_getfrag (struct inode * inode,
return
result
;
}
struct
buffer_head
*
ufs_getfrag
(
struct
inode
*
inode
,
unsigned
fragment
,
int
create
,
int
*
err
)
int
ufs_getfrag_block
(
struct
inode
*
inode
,
long
fragment
,
int
create
,
int
*
err
,
int
*
created
)
{
struct
super_block
*
sb
;
struct
ufs_sb_private_info
*
uspi
;
struct
buffer_head
*
bh
;
struct
buffer_head
*
bh
,
*
tmp
;
unsigned
f
;
unsigned
swab
;
int
phys_block
;
sb
=
inode
->
i_sb
;
uspi
=
sb
->
u
.
ufs_sb
.
s_uspi
;
...
...
@@ -367,19 +417,27 @@ struct buffer_head * ufs_getfrag (struct inode * inode, unsigned fragment,
*
err
=
-
EIO
;
UFSD
((
"ENTER, ino %lu, fragment %u
\n
"
,
inode
->
i_ino
,
fragment
))
if
(
fragment
<
0
)
{
ufs_warning
(
sb
,
"ufs_getblk"
,
"block < 0"
);
return
0
;
}
if
(
fragment
>
((
UFS_NDADDR
+
uspi
->
s_apb
+
uspi
->
s_2apb
+
uspi
->
s_3apb
)
<<
uspi
->
s_fpbshift
))
{
ufs_warning
(
sb
,
"ufs_getblk"
,
"block > big"
);
return
NULL
;
return
0
;
}
*
err
=
-
ENOSPC
;
f
=
fragment
;
*
created
=
0
;
/*
* Direct fragment
*/
if
(
fragment
<
UFS_NDIR_FRAGMENT
)
return
ufs_inode_getfrag
(
inode
,
fragment
,
fragment
,
create
,
1
,
err
);
if
(
fragment
<
UFS_NDIR_FRAGMENT
)
{
tmp
=
ufs_inode_getfrag
(
inode
,
fragment
,
fragment
,
create
,
1
,
err
,
0
,
&
phys_block
,
created
);
goto
out
;
}
/*
* Indirect fragment
*/
...
...
@@ -387,10 +445,12 @@ struct buffer_head * ufs_getfrag (struct inode * inode, unsigned fragment,
if
(
fragment
<
(
1
<<
(
uspi
->
s_apbshift
+
uspi
->
s_fpbshift
)))
{
bh
=
ufs_inode_getfrag
(
inode
,
UFS_IND_FRAGMENT
+
(
fragment
>>
uspi
->
s_apbshift
),
f
,
create
,
uspi
->
s_fpb
,
err
);
return
ufs_block_getfrag
(
inode
,
bh
,
fragment
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
);
f
,
create
,
uspi
->
s_fpb
,
err
,
1
,
NULL
,
NULL
);
tmp
=
ufs_block_getfrag
(
inode
,
bh
,
fragment
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
,
0
,
&
phys_block
,
created
);
goto
out
;
}
/*
* Dindirect fragment
...
...
@@ -398,14 +458,18 @@ struct buffer_head * ufs_getfrag (struct inode * inode, unsigned fragment,
fragment
-=
1
<<
(
uspi
->
s_apbshift
+
uspi
->
s_fpbshift
);
if
(
fragment
<
(
1
<<
(
uspi
->
s_2apbshift
+
uspi
->
s_fpbshift
)))
{
bh
=
ufs_inode_getfrag
(
inode
,
UFS_DIND_FRAGMENT
+
(
fragment
>>
uspi
->
s_2apbshift
),
f
,
create
,
uspi
->
s_fpb
,
err
);
UFS_DIND_FRAGMENT
+
(
fragment
>>
uspi
->
s_2apbshift
),
f
,
create
,
uspi
->
s_fpb
,
err
,
1
,
NULL
,
NULL
);
bh
=
ufs_block_getfrag
(
inode
,
bh
,
(
fragment
>>
uspi
->
s_apbshift
)
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
);
return
ufs_block_getfrag
(
inode
,
bh
,
f
,
create
,
sb
->
s_blocksize
,
err
,
1
,
NULL
,
NULL
);
tmp
=
ufs_block_getfrag
(
inode
,
bh
,
fragment
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
);
f
,
create
,
sb
->
s_blocksize
,
err
,
0
,
&
phys_block
,
created
);
goto
out
;
}
/*
* Tindirect fragment
...
...
@@ -413,19 +477,42 @@ struct buffer_head * ufs_getfrag (struct inode * inode, unsigned fragment,
fragment
-=
1
<<
(
uspi
->
s_2apbshift
+
uspi
->
s_fpbshift
);
bh
=
ufs_inode_getfrag
(
inode
,
UFS_TIND_FRAGMENT
+
(
fragment
>>
uspi
->
s_3apbshift
),
f
,
create
,
uspi
->
s_fpb
,
err
);
f
,
create
,
uspi
->
s_fpb
,
err
,
1
,
NULL
,
NULL
);
bh
=
ufs_block_getfrag
(
inode
,
bh
,
(
fragment
>>
uspi
->
s_2apbshift
)
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
);
f
,
create
,
sb
->
s_blocksize
,
err
,
1
,
NULL
,
NULL
);
bh
=
ufs_block_getfrag
(
inode
,
bh
,
(
fragment
>>
uspi
->
s_apbshift
)
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
);
return
ufs_block_getfrag
(
inode
,
bh
,
f
,
create
,
sb
->
s_blocksize
,
err
,
1
,
NULL
,
NULL
);
tmp
=
ufs_block_getfrag
(
inode
,
bh
,
fragment
&
uspi
->
s_apbmask
,
f
,
create
,
sb
->
s_blocksize
,
err
);
}
f
,
create
,
sb
->
s_blocksize
,
err
,
0
,
&
phys_block
,
created
);
out:
if
(
!
phys_block
)
return
0
;
if
(
*
err
)
return
0
;
return
phys_block
;
}
struct
buffer_head
*
ufs_getfrag
(
struct
inode
*
inode
,
unsigned
int
fragment
,
int
create
,
int
*
err
)
{
struct
buffer_head
*
tmp
=
NULL
;
int
phys_block
,
created
;
phys_block
=
ufs_getfrag_block
(
inode
,
fragment
,
create
,
err
,
&
created
);
if
(
phys_block
)
{
tmp
=
getblk
(
inode
->
i_dev
,
phys_block
,
inode
->
i_sb
->
s_blocksize
);
if
(
created
)
{
memset
(
tmp
->
b_data
,
0
,
inode
->
i_sb
->
s_blocksize
);
mark_buffer_uptodate
(
tmp
,
1
);
mark_buffer_dirty
(
tmp
,
1
);
}
}
return
tmp
;
}
struct
buffer_head
*
ufs_bread
(
struct
inode
*
inode
,
unsigned
fragment
,
int
create
,
int
*
err
)
...
...
fs/ufs/truncate.c
View file @
f6506d68
...
...
@@ -62,6 +62,9 @@
#define DIRECT_BLOCK howmany (inode->i_size, uspi->s_bsize)
#define DIRECT_FRAGMENT howmany (inode->i_size, uspi->s_fsize)
#define DATA_BUFFER_USED(bh) \
((bh->b_count > 1) || buffer_locked(bh))
static
int
ufs_trunc_direct
(
struct
inode
*
inode
)
{
struct
super_block
*
sb
;
...
...
@@ -114,7 +117,7 @@ static int ufs_trunc_direct (struct inode * inode)
frag2
=
ufs_fragnum
(
frag2
);
for
(
j
=
frag1
;
j
<
frag2
;
j
++
)
{
bh
=
get_hash_table
(
sb
->
s_dev
,
tmp
+
j
,
uspi
->
s_fsize
);
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
SWAB32
(
*
p
))
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
SWAB32
(
*
p
))
{
retry
=
1
;
brelse
(
bh
);
goto
next1
;
...
...
@@ -137,7 +140,7 @@ static int ufs_trunc_direct (struct inode * inode)
continue
;
for
(
j
=
0
;
j
<
uspi
->
s_fpb
;
j
++
)
{
bh
=
get_hash_table
(
sb
->
s_dev
,
tmp
+
j
,
uspi
->
s_fsize
);
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
SWAB32
(
*
p
))
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
SWAB32
(
*
p
))
{
retry
=
1
;
brelse
(
bh
);
goto
next2
;
...
...
@@ -176,7 +179,7 @@ static int ufs_trunc_direct (struct inode * inode)
frag4
=
ufs_fragnum
(
frag4
);
for
(
j
=
0
;
j
<
frag4
;
j
++
)
{
bh
=
get_hash_table
(
sb
->
s_dev
,
tmp
+
j
,
uspi
->
s_fsize
);
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
SWAB32
(
*
p
))
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
SWAB32
(
*
p
))
{
retry
=
1
;
brelse
(
bh
);
goto
next1
;
...
...
@@ -237,7 +240,7 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p)
continue
;
for
(
j
=
0
;
j
<
uspi
->
s_fpb
;
j
++
)
{
bh
=
get_hash_table
(
sb
->
s_dev
,
tmp
+
j
,
uspi
->
s_fsize
);
if
((
bh
&&
bh
->
b_count
!=
1
)
||
tmp
!=
SWAB32
(
*
ind
))
{
if
((
bh
&&
DATA_BUFFER_USED
(
bh
)
)
||
tmp
!=
SWAB32
(
*
ind
))
{
retry
=
1
;
brelse
(
bh
);
goto
next
;
...
...
include/linux/fs.h
View file @
f6506d68
...
...
@@ -356,7 +356,6 @@ struct inode {
unsigned
long
i_version
;
unsigned
long
i_nrpages
;
struct
semaphore
i_sem
;
struct
semaphore
i_atomic_write
;
struct
inode_operations
*
i_op
;
struct
super_block
*
i_sb
;
wait_queue_head_t
i_wait
;
...
...
@@ -622,7 +621,7 @@ struct inode_operations {
int
(
*
smap
)
(
struct
inode
*
,
int
);
int
(
*
updatepage
)
(
struct
file
*
,
struct
page
*
,
unsigned
long
,
unsigned
int
);
int
(
*
revalidate
)
(
struct
dentry
*
);
int
(
*
flushpage
)
(
struct
inode
*
,
struct
page
*
,
int
);
int
(
*
flushpage
)
(
struct
inode
*
,
struct
page
*
,
unsigned
long
);
};
struct
super_operations
{
...
...
@@ -750,15 +749,7 @@ extern struct file *inuse_filps;
extern
void
set_writetime
(
struct
buffer_head
*
,
int
);
extern
int
try_to_free_buffers
(
struct
page
*
);
extern
void
__refile_buffer
(
struct
buffer_head
*
buf
);
extern
inline
void
refile_buffer
(
struct
buffer_head
*
buf
)
{
/*
* Subtle, we do not want to refile not hashed buffers ...
*/
if
(
buf
->
b_pprev
)
__refile_buffer
(
buf
);
}
extern
void
refile_buffer
(
struct
buffer_head
*
buf
);
extern
int
buffermem
;
...
...
@@ -881,8 +872,10 @@ extern int generic_readpage(struct file *, struct page *);
extern
int
generic_file_mmap
(
struct
file
*
,
struct
vm_area_struct
*
);
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
*
,
writepage_t
);
extern
int
generic_block_flushpage
(
struct
inode
*
,
struct
page
*
,
int
);
extern
long
block_write_one_page
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
bytes
,
const
char
*
buf
,
fs_getblock_t
fs_get_block
);
extern
int
generic_block_flushpage
(
struct
inode
*
,
struct
page
*
,
unsigned
long
);
extern
int
block_write_one_page
(
struct
file
*
file
,
struct
page
*
page
,
unsigned
long
offset
,
unsigned
long
bytes
,
const
char
*
buf
,
fs_getblock_t
fs_get_block
);
extern
int
block_write_full_page
(
struct
file
*
file
,
struct
page
*
page
,
fs_getblock_t
fs_get_block
);
extern
struct
super_block
*
get_super
(
kdev_t
);
extern
void
put_super
(
kdev_t
);
...
...
include/linux/minix_fs.h
View file @
f6506d68
...
...
@@ -110,6 +110,7 @@ extern unsigned long minix_count_free_blocks(struct super_block *sb);
extern
int
minix_bmap
(
struct
inode
*
,
int
);
extern
struct
buffer_head
*
minix_getblk
(
struct
inode
*
,
int
,
int
);
extern
int
minix_getblk_block
(
struct
inode
*
,
long
,
int
,
int
*
,
int
*
);
extern
struct
buffer_head
*
minix_bread
(
struct
inode
*
,
int
,
int
);
extern
void
minix_truncate
(
struct
inode
*
);
...
...
include/linux/nfs_fs.h
View file @
f6506d68
...
...
@@ -192,7 +192,8 @@ extern struct inode_operations nfs_file_inode_operations;
*/
extern
struct
inode_operations
nfs_dir_inode_operations
;
extern
struct
dentry_operations
nfs_dentry_operations
;
extern
void
nfs_invalidate_dircache
(
struct
inode
*
);
extern
void
nfs_flush_dircache
(
struct
inode
*
);
extern
void
nfs_free_dircache
(
struct
inode
*
);
/*
* linux/fs/nfs/symlink.c
...
...
include/linux/sysv_fs.h
View file @
f6506d68
...
...
@@ -387,6 +387,7 @@ extern unsigned long sysv_count_free_blocks(struct super_block *sb);
extern
int
sysv_bmap
(
struct
inode
*
,
int
);
extern
struct
buffer_head
*
sysv_getblk
(
struct
inode
*
,
unsigned
int
,
int
);
extern
int
sysv_getblk_block
(
struct
inode
*
,
long
,
int
,
int
*
,
int
*
);
extern
struct
buffer_head
*
sysv_file_bread
(
struct
inode
*
,
int
,
int
);
extern
ssize_t
sysv_file_read
(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
...
...
include/linux/ufs_fs.h
View file @
f6506d68
...
...
@@ -537,6 +537,7 @@ extern int ufs_sync_inode (struct inode *);
extern
void
ufs_write_inode
(
struct
inode
*
);
extern
void
ufs_delete_inode
(
struct
inode
*
);
extern
struct
buffer_head
*
ufs_getfrag
(
struct
inode
*
,
unsigned
,
int
,
int
*
);
extern
int
ufs_getfrag_block
(
struct
inode
*
,
long
,
int
,
int
*
,
int
*
);
extern
struct
buffer_head
*
ufs_bread
(
struct
inode
*
,
unsigned
,
int
,
int
*
);
/* namei.c */
...
...
mm/filemap.c
View file @
f6506d68
...
...
@@ -137,8 +137,6 @@ void truncate_inode_pages(struct inode * inode, unsigned long start)
page_cache_release
(
page
);
goto
repeat
;
}
if
(
page_count
(
page
)
!=
2
)
printk
(
"hm, busy page truncated? (not necesserily a bug)
\n
"
);
spin_unlock
(
&
pagecache_lock
);
if
(
inode
->
i_op
->
flushpage
)
...
...
@@ -160,9 +158,6 @@ void truncate_inode_pages(struct inode * inode, unsigned long start)
page
->
prev
=
NULL
;
remove_page_from_hash_queue
(
page
);
page
->
inode
=
NULL
;
if
(
page_count
(
page
)
!=
2
)
printk
(
"hm, busy page truncated? (not necesserily a bug)
\n
"
);
spin_unlock
(
&
pagecache_lock
);
UnlockPage
(
page
);
...
...
@@ -189,6 +184,13 @@ void truncate_inode_pages(struct inode * inode, unsigned long start)
/* partial truncate, clear end of page */
if
(
offset
<
PAGE_CACHE_SIZE
)
{
unsigned
long
address
;
get_page
(
page
);
if
(
TryLockPage
(
page
))
{
spin_unlock
(
&
pagecache_lock
);
wait_on_page
(
page
);
page_cache_release
(
page
);
goto
repeat
;
}
/*
* It's worth dropping the write lock only at
* this point. We are holding the page lock
...
...
@@ -200,10 +202,15 @@ void truncate_inode_pages(struct inode * inode, unsigned long start)
address
=
page_address
(
page
);
memset
((
void
*
)
(
offset
+
address
),
0
,
PAGE_CACHE_SIZE
-
offset
);
flush_page_to_ram
(
address
);
if
(
inode
->
i_op
->
flushpage
)
inode
->
i_op
->
flushpage
(
inode
,
page
,
offset
);
/*
* we have dropped the lock so we have to
* we have dropped the
spin
lock so we have to
* restart.
*/
UnlockPage
(
page
);
page_cache_release
(
page
);
goto
repeat
;
}
}
...
...
@@ -217,25 +224,9 @@ void truncate_inode_pages(struct inode * inode, unsigned long start)
*/
void
remove_inode_page
(
struct
page
*
page
)
{
struct
inode
*
inode
=
page
->
inode
;
if
(
!
PageLocked
(
page
))
PAGE_BUG
(
page
);
/*
* We might sleep here. Other processes might arrive and sleep on
* the lock, but nobody is allowed to 'cross' the lock and get a
* reference to the page. We then remove the page from the hash
* before unlocking it. This mechanizm ensures that 1) nobody gets
* a half-freed page 2) nobody creates the same pagecache content
* before we finish destroying this page. This is not a
* performance problem as pages here are candidates for getting
* freed, ie. it's supposed to be unlikely that the above situation
* happens.
*/
if
(
inode
->
i_op
->
flushpage
)
inode
->
i_op
->
flushpage
(
inode
,
page
,
1
);
spin_lock
(
&
pagecache_lock
);
remove_page_from_inode_queue
(
page
);
remove_page_from_hash_queue
(
page
);
...
...
@@ -274,12 +265,27 @@ int shrink_mmap(int priority, int gfp_mask)
referenced
=
test_and_clear_bit
(
PG_referenced
,
&
page
->
flags
);
if
(
PageLocked
(
page
))
if
(
(
gfp_mask
&
__GFP_DMA
)
&&
!
PageDMA
(
page
))
continue
;
if
(
(
gfp_mask
&
__GFP_DMA
)
&&
!
PageDMA
(
page
))
if
(
PageLocked
(
page
))
continue
;
/* Is it a buffer page? */
if
(
page
->
buffers
)
{
if
(
buffer_under_min
())
continue
;
if
(
TryLockPage
(
page
))
continue
;
err
=
try_to_free_buffers
(
page
);
UnlockPage
(
page
);
if
(
!
err
)
continue
;
goto
out
;
}
/* We can't free pages unless there's just one user */
if
(
page_count
(
page
)
!=
1
)
continue
;
...
...
@@ -309,13 +315,14 @@ int shrink_mmap(int priority, int gfp_mask)
goto
unlock_continue
;
if
(
TryLockPage
(
page
))
goto
unlock_continue
;
if
(
page_count
(
page
)
!=
1
)
{
UnlockPage
(
page
);
goto
unlock_continue
;
if
(
page_count
(
page
)
==
1
)
{
remove_page_from_inode_queue
(
page
);
remove_page_from_hash_queue
(
page
);
page
->
inode
=
NULL
;
}
spin_unlock
(
&
pagecache_lock
);
remove_inode_page
(
page
);
UnlockPage
(
page
);
page_cache_release
(
page
);
err
=
1
;
...
...
@@ -325,17 +332,6 @@ int shrink_mmap(int priority, int gfp_mask)
continue
;
}
spin_unlock
(
&
pagecache_lock
);
/* Is it a buffer page? */
if
(
page
->
buffers
)
{
if
(
buffer_under_min
())
continue
;
if
(
!
try_to_free_buffers
(
page
))
continue
;
err
=
1
;
goto
out
;
}
}
while
(
count
>
0
);
err
=
0
;
out:
...
...
@@ -1086,17 +1082,14 @@ static int file_send_actor(read_descriptor_t * desc, const char *area, unsigned
ssize_t
written
;
unsigned
long
count
=
desc
->
count
;
struct
file
*
file
=
(
struct
file
*
)
desc
->
buf
;
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
mm_segment_t
old_fs
;
if
(
size
>
count
)
size
=
count
;
down
(
&
inode
->
i_sem
);
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
written
=
file
->
f_op
->
write
(
file
,
area
,
size
,
&
file
->
f_pos
);
set_fs
(
old_fs
);
up
(
&
inode
->
i_sem
);
if
(
written
<
0
)
{
desc
->
error
=
written
;
written
=
0
;
...
...
@@ -1362,7 +1355,6 @@ static inline int do_write_page(struct inode * inode, struct file * file,
int
retval
;
unsigned
long
size
;
loff_t
loff
=
offset
;
mm_segment_t
old_fs
;
int
(
*
writepage
)
(
struct
file
*
,
struct
page
*
);
struct
page
*
page
;
...
...
@@ -1376,8 +1368,6 @@ static inline int do_write_page(struct inode * inode, struct file * file,
return
-
EIO
;
}
size
-=
offset
;
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
retval
=
-
EIO
;
writepage
=
inode
->
i_op
->
writepage
;
page
=
mem_map
+
MAP_NR
(
page_addr
);
...
...
@@ -1386,11 +1376,13 @@ static inline int do_write_page(struct inode * inode, struct file * file,
if
(
writepage
)
{
retval
=
writepage
(
file
,
page
);
}
else
{
mm_segment_t
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
if
(
size
==
file
->
f_op
->
write
(
file
,
page_addr
,
size
,
&
loff
))
retval
=
0
;
retval
=
0
;
set_fs
(
old_fs
);
}
UnlockPage
(
page
);
set_fs
(
old_fs
);
return
retval
;
}
...
...
@@ -1426,9 +1418,7 @@ static int filemap_write_page(struct vm_area_struct * vma,
return
0
;
}
down
(
&
inode
->
i_sem
);
result
=
do_write_page
(
inode
,
file
,
(
const
char
*
)
page
,
offset
);
up
(
&
inode
->
i_sem
);
fput
(
file
);
return
result
;
}
...
...
@@ -1642,10 +1632,7 @@ static int msync_interval(struct vm_area_struct * vma,
struct
file
*
file
=
vma
->
vm_file
;
if
(
file
)
{
struct
dentry
*
dentry
=
file
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
down
(
&
inode
->
i_sem
);
error
=
file_fsync
(
file
,
dentry
);
up
(
&
inode
->
i_sem
);
}
}
return
error
;
...
...
@@ -1972,10 +1959,8 @@ int kpiod(void * unused)
dentry
=
p
->
file
->
f_dentry
;
inode
=
dentry
->
d_inode
;
down
(
&
inode
->
i_sem
);
do_write_page
(
inode
,
p
->
file
,
(
const
char
*
)
p
->
page
,
p
->
offset
);
up
(
&
inode
->
i_sem
);
fput
(
p
->
file
);
page_cache_free
(
p
->
page
);
kmem_cache_free
(
pio_request_cache
,
p
);
...
...
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