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
c6145b38
Commit
c6145b38
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 0.99.14j
parent
27c43263
Changes
29
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1159 additions
and
759 deletions
+1159
-759
Makefile
Makefile
+1
-1
drivers/sound/Makefile
drivers/sound/Makefile
+1
-1
drivers/sound/sb16_dsp.c
drivers/sound/sb16_dsp.c
+1
-1
fs/ext2/acl.c
fs/ext2/acl.c
+9
-4
fs/ext2/balloc.c
fs/ext2/balloc.c
+213
-196
fs/ext2/bitmap.c
fs/ext2/bitmap.c
+3
-1
fs/ext2/dcache.c
fs/ext2/dcache.c
+3
-2
fs/ext2/dir.c
fs/ext2/dir.c
+38
-10
fs/ext2/file.c
fs/ext2/file.c
+57
-20
fs/ext2/fsync.c
fs/ext2/fsync.c
+5
-1
fs/ext2/ialloc.c
fs/ext2/ialloc.c
+92
-137
fs/ext2/inode.c
fs/ext2/inode.c
+96
-9
fs/ext2/ioctl.c
fs/ext2/ioctl.c
+3
-1
fs/ext2/namei.c
fs/ext2/namei.c
+106
-46
fs/ext2/super.c
fs/ext2/super.c
+299
-164
fs/ext2/symlink.c
fs/ext2/symlink.c
+3
-1
fs/ext2/truncate.c
fs/ext2/truncate.c
+9
-16
fs/super.c
fs/super.c
+64
-47
include/asm/io.h
include/asm/io.h
+76
-68
include/asm/irq.h
include/asm/irq.h
+1
-1
include/linux/ext2_fs.h
include/linux/ext2_fs.h
+57
-16
include/linux/ext2_fs_i.h
include/linux/ext2_fs_i.h
+5
-1
include/linux/ext2_fs_sb.h
include/linux/ext2_fs_sb.h
+4
-1
include/linux/fs.h
include/linux/fs.h
+1
-1
include/linux/net.h
include/linux/net.h
+1
-1
include/linux/nfs.h
include/linux/nfs.h
+8
-8
include/linux/sockios.h
include/linux/sockios.h
+1
-1
net/inet/route.c
net/inet/route.c
+1
-1
tools/version.c
tools/version.c
+1
-2
No files found.
Makefile
View file @
c6145b38
VERSION
=
0.99
PATCHLEVEL
=
14
ALPHA
=
i
ALPHA
=
j
all
:
Version zImage
...
...
drivers/sound/Makefile
View file @
c6145b38
...
...
@@ -5,7 +5,7 @@
#
#
VERSION
=
2.3
VERSION
=
2.3
b
TARGET_OS
=
linux
.c.s
:
...
...
drivers/sound/sb16_dsp.c
View file @
c6145b38
...
...
@@ -178,7 +178,7 @@ static int dsp_set_stereo(int mode)
{
DEB
(
printk
(
"dsp_set_stereo(%d)
\n
"
,
mode
));
if
(
mode
)
dsp_stereo
=
mode
;
dsp_stereo
=
mode
;
return
mode
;
}
...
...
fs/ext2/acl.c
View file @
c6145b38
/*
* linux/fs/ext2/acl.c
*
* Copyright (C) 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*/
/*
...
...
@@ -12,7 +14,6 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/stat.h>
...
...
@@ -25,10 +26,14 @@ int ext2_permission (struct inode * inode, int mask)
{
unsigned
short
mode
=
inode
->
i_mode
;
/* Special case, access is always granted for root */
/*
* Special case, access is always granted for root
*/
if
(
suser
())
return
1
;
/* If no ACL, checks using the file mode */
/*
* If no ACL, checks using the file mode
*/
else
if
(
current
->
euid
==
inode
->
i_uid
)
mode
>>=
6
;
else
if
(
in_group_p
(
inode
->
i_gid
))
...
...
fs/ext2/balloc.c
View file @
c6145b38
/*
* linux/fs/ext2/balloc.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
*/
/* balloc.c contains the blocks allocation and deallocation routines */
/*
* balloc.c contains the blocks allocation and deallocation routines
*/
The free blocks are managed by bitmaps. A file system contains several
blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
block for inodes, N blocks for the inode table and data blocks.
The file system contains group descriptors which are located after the
super block. Each descriptor contains the number of the bitmap block and
the free blocks count in the block. The descriptors are loaded in memory
when a file system is mounted (see ext2_read_super).
*/
/*
* The free blocks are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* block for inodes, N blocks for the inode table and data blocks.
*
* The file system contains group descriptors which are located after the
* super block. Each descriptor contains the number of the bitmap block and
* the free blocks count in the block. The descriptors are loaded in memory
* when a file system is mounted (see ext2_read_super).
*/
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/string.h>
...
...
@@ -39,6 +40,8 @@
:"a" (0), "c" (size / 4), "D" ((long) (addr)) \
:"cx", "di")
#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
static
inline
int
find_first_zero_bit
(
unsigned
long
*
addr
,
unsigned
size
)
{
int
res
;
...
...
@@ -72,7 +75,9 @@ static inline int find_next_zero_bit (unsigned long * addr, int size,
int
set
=
0
,
bit
=
offset
&
31
,
res
;
if
(
bit
)
{
/* Look for zero in first byte */
/*
* Look for zero in first byte
*/
__asm__
(
"
bsfl %1,%0
jne 1f
...
...
@@ -85,7 +90,9 @@ static inline int find_next_zero_bit (unsigned long * addr, int size,
set
=
32
-
bit
;
p
++
;
}
/* No zero yet, search remaining full bytes for a zero */
/*
* No zero yet, search remaining full bytes for a zero
*/
res
=
find_first_zero_bit
(
p
,
size
-
32
*
(
p
-
addr
));
return
(
offset
+
set
+
res
);
}
...
...
@@ -109,32 +116,48 @@ static inline char * find_first_zero_byte (char * addr, int size)
return
res
;
}
static
void
read_block_bitmap
(
struct
super_block
*
sb
,
static
struct
ext2_group_desc
*
get_group_desc
(
struct
super_block
*
sb
,
unsigned
int
block_group
,
unsigned
long
bitmap_nr
)
struct
buffer_head
**
bh
)
{
unsigned
long
group_desc
;
unsigned
long
desc
;
struct
ext2_group_desc
*
gdp
;
struct
buffer_head
*
bh
;
if
(
block_group
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
ext2_panic
(
sb
,
"get_group_desc"
,
"block_group >= groups_count
\n
"
"block_group = %d, groups_count = %lu"
,
block_group
,
sb
->
u
.
ext2_sb
.
s_groups_count
);
group_desc
=
block_group
/
EXT2_DESC_PER_BLOCK
(
sb
);
desc
=
block_group
%
EXT2_DESC_PER_BLOCK
(
sb
);
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
])
ext2_panic
(
sb
,
"
read_block_bitmap
"
,
ext2_panic
(
sb
,
"
get_group_desc
"
,
"Group descriptor not loaded
\n
"
"block_group = %d, group_desc = %lu, desc = %lu"
,
block_group
,
group_desc
,
desc
);
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
bh
=
bread
(
sb
->
s_dev
,
gdp
[
desc
].
bg_block_bitmap
,
sb
->
s_blocksize
);
if
(
bh
)
*
bh
=
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
];
return
gdp
+
desc
;
}
static
void
read_block_bitmap
(
struct
super_block
*
sb
,
unsigned
int
block_group
,
unsigned
long
bitmap_nr
)
{
struct
ext2_group_desc
*
gdp
;
struct
buffer_head
*
bh
;
gdp
=
get_group_desc
(
sb
,
block_group
,
NULL
);
bh
=
bread
(
sb
->
s_dev
,
gdp
->
bg_block_bitmap
,
sb
->
s_blocksize
);
if
(
!
bh
)
ext2_panic
(
sb
,
"read_block_bitmap"
,
"Cannot read block bitmap
\n
"
"block_group = %d, group_desc = %lu,"
"desc = %lu, block_bitmap = %lu"
,
block_group
,
group_desc
,
desc
,
gdp
[
desc
].
bg_block_bitmap
);
"block_group = %d, block_bitmap = %lu"
,
block_group
,
gdp
->
bg_block_bitmap
);
sb
->
u
.
ext2_sb
.
s_block_bitmap_number
[
bitmap_nr
]
=
block_group
;
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
]
=
bh
;
}
...
...
@@ -193,12 +216,10 @@ static int load__block_bitmap (struct super_block * sb,
sb
->
u
.
ext2_sb
.
s_block_bitmap_number
[
0
]
=
block_bitmap_number
;
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
0
]
=
block_bitmap
;
}
else
{
if
(
sb
->
u
.
ext2_sb
.
s_loaded_block_bitmaps
<
EXT2_MAX_GROUP_LOADED
)
if
(
sb
->
u
.
ext2_sb
.
s_loaded_block_bitmaps
<
EXT2_MAX_GROUP_LOADED
)
sb
->
u
.
ext2_sb
.
s_loaded_block_bitmaps
++
;
else
brelse
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
EXT2_MAX_GROUP_LOADED
-
1
]);
brelse
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
EXT2_MAX_GROUP_LOADED
-
1
]);
for
(
j
=
sb
->
u
.
ext2_sb
.
s_loaded_block_bitmaps
-
1
;
j
>
0
;
j
--
)
{
sb
->
u
.
ext2_sb
.
s_block_bitmap_number
[
j
]
=
sb
->
u
.
ext2_sb
.
s_block_bitmap_number
[
j
-
1
];
...
...
@@ -225,64 +246,70 @@ static inline int load_block_bitmap (struct super_block * sb,
return
load__block_bitmap
(
sb
,
block_group
);
}
void
ext2_free_block
(
struct
super_block
*
sb
,
unsigned
long
block
)
void
ext2_free_blocks
(
struct
super_block
*
sb
,
unsigned
long
block
,
unsigned
long
count
)
{
struct
buffer_head
*
bh
;
struct
buffer_head
*
bh2
;
unsigned
long
block_group
;
unsigned
long
bit
;
unsigned
long
group_desc
;
unsigned
long
desc
;
unsigned
long
i
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
struct
ext2_super_block
*
es
;
if
(
!
sb
)
{
printk
(
"ext2_free_block: nonexistent device"
);
printk
(
"ext2_free_block
s
: nonexistent device"
);
return
;
}
lock_super
(
sb
);
es
=
sb
->
u
.
ext2_sb
.
s_es
;
if
(
block
<
es
->
s_first_data_block
||
block
>=
es
->
s_blocks_count
)
{
ext2_error
(
sb
,
"ext2_free_block"
,
"block not in datazone"
);
if
(
block
<
es
->
s_first_data_block
||
(
block
+
count
)
>
es
->
s_blocks_count
)
{
ext2_error
(
sb
,
"ext2_free_blocks"
,
"Freeing blocks not in datazone"
);
unlock_super
(
sb
);
return
;
}
ext2_debug
(
"freeing block %lu
\n
"
,
block
);
#if 0 /* XXX - This is incompatible with the secure rm implemented in 0.4 */
bh = get_hash_table (sb->s_dev, block, sb->s_blocksize);
if (bh)
bh->b_dirt = 0;
brelse (bh);
#endif
block_group
=
(
block
-
es
->
s_first_data_block
)
/
EXT2_BLOCKS_PER_GROUP
(
sb
);
bit
=
(
block
-
es
->
s_first_data_block
)
%
EXT2_BLOCKS_PER_GROUP
(
sb
);
if
(
bit
+
count
>
EXT2_BLOCKS_PER_GROUP
(
sb
))
ext2_panic
(
sb
,
"ext2_free_blocks"
,
"Freeing blocks across group boundary
\n
"
"Block = %lu, count = %lu"
,
block
,
count
);
bitmap_nr
=
load_block_bitmap
(
sb
,
block_group
);
bh
=
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
];
if
(
!
bh
)
ext2_panic
(
sb
,
"ext2_free_block"
,
"Unable to load group bitmap
\n
"
"block_group = %lu"
,
block_group
);
if
(
!
clear_bit
(
bit
,
bh
->
b_data
))
ext2_warning
(
sb
,
"ext2_free_block"
,
"bit already cleared for block %lu"
,
block
);
else
{
group_desc
=
block_group
/
EXT2_DESC_PER_BLOCK
(
sb
);
desc
=
block_group
%
EXT2_DESC_PER_BLOCK
(
sb
);
bh2
=
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
];
if
(
!
bh2
)
ext2_panic
(
sb
,
"ext2_free_block"
,
"Group descriptor not loaded
\n
"
"group_desc = %lu"
,
group_desc
);
gdp
=
(
struct
ext2_group_desc
*
)
bh2
->
b_data
;
gdp
[
desc
].
bg_free_blocks_count
++
;
gdp
=
get_group_desc
(
sb
,
block_group
,
&
bh2
);
if
(
test_opt
(
sb
,
CHECK_STRICT
)
&&
(
in_range
(
gdp
->
bg_block_bitmap
,
block
,
count
)
||
in_range
(
gdp
->
bg_inode_bitmap
,
block
,
count
)
||
in_range
(
block
,
gdp
->
bg_inode_table
,
sb
->
u
.
ext2_sb
.
s_itb_per_group
)
||
in_range
(
block
+
count
-
1
,
gdp
->
bg_inode_table
,
sb
->
u
.
ext2_sb
.
s_itb_per_group
)))
ext2_panic
(
sb
,
"ext2_free_blocks"
,
"Freeing blocks in system zones
\n
"
"Block = %lu, count = %lu"
,
block
,
count
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
!
clear_bit
(
bit
+
i
,
bh
->
b_data
))
ext2_warning
(
sb
,
"ext2_free_blocks"
,
"bit already cleared for block %lu"
,
block
);
}
gdp
->
bg_free_blocks_count
+=
count
;
bh2
->
b_dirt
=
1
;
es
->
s_free_blocks_count
++
;
es
->
s_free_blocks_count
+=
count
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
}
bh
->
b_dirt
=
1
;
if
(
sb
->
s_flags
&
MS_SYNC
)
{
ll_rw_block
(
WRITE
,
1
,
&
bh
);
...
...
@@ -300,14 +327,15 @@ void ext2_free_block (struct super_block * sb, unsigned long block)
* each block group the search first looks for an entire free byte in the block
* bitmap, and then for any free bit if that fails.
*/
int
ext2_new_block
(
struct
super_block
*
sb
,
unsigned
long
goal
)
int
ext2_new_block
(
struct
super_block
*
sb
,
unsigned
long
goal
,
unsigned
long
*
prealloc_count
,
unsigned
long
*
prealloc_block
)
{
struct
buffer_head
*
bh
;
char
*
p
,
*
r
;
int
i
,
j
,
k
;
struct
buffer_head
*
bh2
;
char
*
p
,
*
r
;
int
i
,
j
,
k
,
tmp
;
unsigned
long
lmap
;
unsigned
long
group_desc
;
unsigned
long
desc
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
struct
ext2_super_block
*
es
;
...
...
@@ -329,34 +357,21 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
ext2_debug
(
"goal=%lu.
\n
"
,
goal
);
repeat:
/* First, test whether the goal block is free. */
/*
* First, test whether the goal block is free.
*/
i
=
((
goal
-
es
->
s_first_data_block
)
/
EXT2_BLOCKS_PER_GROUP
(
sb
));
group_desc
=
i
/
EXT2_DESC_PER_BLOCK
(
sb
);
desc
=
i
%
EXT2_DESC_PER_BLOCK
(
sb
);
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
if
(
!
gdp
)
{
ext2_panic
(
sb
,
"ext2_new_block"
,
"Descriptor not loaded for group %d"
,
i
);
}
if
(
gdp
[
desc
].
bg_free_blocks_count
>
0
)
{
j
=
((
goal
-
es
->
s_first_data_block
)
%
EXT2_BLOCKS_PER_GROUP
(
sb
));
gdp
=
get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
gdp
->
bg_free_blocks_count
>
0
)
{
j
=
((
goal
-
es
->
s_first_data_block
)
%
EXT2_BLOCKS_PER_GROUP
(
sb
));
#ifdef EXT2FS_DEBUG
if
(
j
)
goal_attempts
++
;
#endif
bitmap_nr
=
load_block_bitmap
(
sb
,
i
);
bh
=
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
];
if
(
!
bh
)
{
ext2_panic
(
sb
,
"ext2_new_block"
,
"Cannot load bitmap %d"
,
bitmap_nr
);
unlock_super
(
sb
);
return
0
;
}
ext2_debug
(
"goal is at %d[%lu,%lu]:%d.
\n
"
,
i
,
group_desc
,
desc
,
j
);
ext2_debug
(
"goal is at %d:%d.
\n
"
,
i
,
j
);
if
(
!
test_bit
(
j
,
bh
->
b_data
))
{
#ifdef EXT2FS_DEBUG
...
...
@@ -366,8 +381,10 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
goto
got_block
;
}
if
(
j
)
{
/* The goal was occupied; search forward for a free
block within the next 32 blocks */
/*
* The goal was occupied; search forward for a free
* block within the next 32 blocks
*/
lmap
=
((((
unsigned
long
*
)
bh
->
b_data
)[
j
>>
5
])
>>
((
j
&
31
)
+
1
));
if
(
j
<
EXT2_BLOCKS_PER_GROUP
(
sb
)
-
32
)
...
...
@@ -389,20 +406,22 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
ext2_debug
(
"Bit not found near goal
\n
"
);
/* There has been no free block found in the near vicinity
of the goal: do a search forward through the block groups,
searching in each group first for an entire free byte in
the bitmap and then for any free bit.
Search first in the remainder of the current group; then,
cyclicly search throught the rest of the groups. */
/*
* There has been no free block found in the near vicinity
* of the goal: do a search forward through the block groups,
* searching in each group first for an entire free byte in
* the bitmap and then for any free bit.
*
* Search first in the remainder of the current group; then,
* cyclicly search throught the rest of the groups.
*/
p
=
((
char
*
)
bh
->
b_data
)
+
(
j
>>
3
);
r
=
find_first_zero_byte
(
p
,
(
EXT2_BLOCKS_PER_GROUP
(
sb
)
-
j
+
7
)
>>
3
);
k
=
(
r
-
((
char
*
)
bh
->
b_data
))
<<
3
;
if
(
k
<
EXT2_BLOCKS_PER_GROUP
(
sb
))
{
j
=
k
;
goto
got_blo
ck
;
goto
search_ba
ck
;
}
k
=
find_next_zero_bit
((
unsigned
long
*
)
bh
->
b_data
,
EXT2_BLOCKS_PER_GROUP
(
sb
),
...
...
@@ -415,32 +434,16 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
ext2_debug
(
"Bit not found in block group %d.
\n
"
,
i
);
/* Now search the rest of the groups. We assume that group_desc, desc,
i and gdp correctly point to the last group visited. */
/*
* Now search the rest of the groups. We assume that
* i and gdp correctly point to the last group visited.
*/
for
(
k
=
0
;
k
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
k
++
)
{
i
++
;
if
(
i
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
{
if
(
i
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
i
=
0
;
group_desc
=
0
;
desc
=
0
;
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
}
else
{
desc
++
;
if
(
desc
>=
EXT2_DESC_PER_BLOCK
(
sb
))
{
group_desc
++
;
desc
=
0
;
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
}
}
if
(
!
gdp
)
{
ext2_panic
(
sb
,
"ext2_new_block"
,
"Descriptor not loaded for group %d"
,
i
);
}
if
(
gdp
[
desc
].
bg_free_blocks_count
>
0
)
gdp
=
get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
gdp
->
bg_free_blocks_count
>
0
)
break
;
}
if
(
k
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
{
...
...
@@ -449,13 +452,12 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
}
bitmap_nr
=
load_block_bitmap
(
sb
,
i
);
bh
=
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
];
if
(
!
bh
)
ext2_panic
(
sb
,
"ext2_new_block"
,
"Unable to load bitmap for group %d"
,
i
);
r
=
find_first_zero_byte
(
bh
->
b_data
,
EXT2_BLOCKS_PER_GROUP
(
sb
)
>>
3
);
j
=
(
r
-
bh
->
b_data
)
<<
3
;
if
(
j
>=
EXT2_BLOCKS_PER_GROUP
(
sb
))
if
(
j
<
EXT2_BLOCKS_PER_GROUP
(
sb
))
goto
search_back
;
else
j
=
find_first_zero_bit
((
unsigned
long
*
)
bh
->
b_data
,
EXT2_BLOCKS_PER_GROUP
(
sb
));
if
(
j
>=
EXT2_BLOCKS_PER_GROUP
(
sb
))
{
...
...
@@ -465,25 +467,64 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
return
0
;
}
search_back:
/*
* We have succeeded in finding a free byte in the block
* bitmap. Now search backwards up to 7 bits to find the
* start of this group of free blocks.
*/
for
(
k
=
0
;
k
<
7
&&
j
>
0
&&
!
test_bit
(
j
-
1
,
bh
->
b_data
);
k
++
,
j
--
);
got_block:
ext2_debug
(
"using block group %d(%lu,%lu,%d)
\n
"
,
i
,
group_desc
,
desc
,
gdp
[
desc
].
bg_free_blocks_count
);
ext2_debug
(
"using block group %d(%d)
\n
"
,
i
,
gdp
->
bg_free_blocks_count
);
tmp
=
j
+
i
*
EXT2_BLOCKS_PER_GROUP
(
sb
)
+
es
->
s_first_data_block
;
if
(
test_opt
(
sb
,
CHECK_STRICT
)
&&
(
tmp
==
gdp
->
bg_block_bitmap
||
tmp
==
gdp
->
bg_inode_bitmap
||
in_range
(
tmp
,
gdp
->
bg_inode_table
,
sb
->
u
.
ext2_sb
.
s_itb_per_group
)))
ext2_panic
(
sb
,
"ext2_new_block"
,
"Allocating block in system zone
\n
block = %u"
,
tmp
);
if
(
set_bit
(
j
,
bh
->
b_data
))
{
ext2_warning
(
sb
,
"ext2_new_block"
,
"bit already set for block %d"
,
j
);
goto
repeat
;
}
ext2_debug
(
"found bit %d
\n
"
,
j
);
/*
* Do block preallocation now if required.
*/
#ifdef EXT2_PREALLOCATE
if
(
prealloc_block
)
{
*
prealloc_count
=
0
;
*
prealloc_block
=
tmp
+
1
;
for
(
k
=
1
;
k
<
8
&&
(
j
+
k
)
<
EXT2_BLOCKS_PER_GROUP
(
sb
);
k
++
)
{
if
(
set_bit
(
j
+
k
,
bh
->
b_data
))
break
;
(
*
prealloc_count
)
++
;
}
gdp
->
bg_free_blocks_count
-=
*
prealloc_count
;
es
->
s_free_blocks_count
-=
*
prealloc_count
;
ext2_debug
(
"Preallocated a further %lu bits.
\n
"
,
*
prealloc_count
);
}
#endif
j
=
tmp
;
bh
->
b_dirt
=
1
;
if
(
sb
->
s_flags
&
MS_SYNC
)
{
ll_rw_block
(
WRITE
,
1
,
&
bh
);
wait_on_buffer
(
bh
);
}
ext2_debug
(
"found bit %d
\n
"
,
j
);
j
+=
i
*
EXT2_BLOCKS_PER_GROUP
(
sb
)
+
es
->
s_first_data_block
;
if
(
j
>=
es
->
s_blocks_count
)
{
ext2_error
(
sb
,
"ext2_new_block"
,
"block >= blocks count
\n
"
...
...
@@ -504,8 +545,8 @@ int ext2_new_block (struct super_block * sb, unsigned long goal)
ext2_debug
(
"allocating block %d. "
"Goal hits %d of %d.
\n
"
,
j
,
goal_hits
,
goal_attempts
);
gdp
[
desc
].
bg_free_blocks_count
--
;
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_dirt
=
1
;
gdp
->
bg_free_blocks_count
--
;
bh2
->
b_dirt
=
1
;
es
->
s_free_blocks_count
--
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
sb
->
s_dirt
=
1
;
...
...
@@ -518,8 +559,6 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
#ifdef EXT2FS_DEBUG
struct
ext2_super_block
*
es
;
unsigned
long
desc_count
,
bitmap_count
,
x
;
unsigned
long
group_desc
;
unsigned
long
desc
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
int
i
;
...
...
@@ -528,38 +567,16 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
es
=
sb
->
u
.
ext2_sb
.
s_es
;
desc_count
=
0
;
bitmap_count
=
0
;
group_desc
=
0
;
desc
=
0
;
gdp
=
NULL
;
for
(
i
=
0
;
i
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
i
++
)
{
if
(
!
gdp
)
{
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
])
{
printk
(
"ext2_count_free_block: "
"Descriptor not loaded
\n
"
);
break
;
}
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
}
desc_count
+=
gdp
[
desc
].
bg_free_blocks_count
;
gdp
=
get_group_desc
(
sb
,
i
,
NULL
);
desc_count
+=
gdp
->
bg_free_blocks_count
;
bitmap_nr
=
load_block_bitmap
(
sb
,
i
);
if
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
])
x
=
ext2_count_free
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
],
x
=
ext2_count_free
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
],
sb
->
s_blocksize
);
else
{
x
=
0
;
printk
(
"Cannot load bitmap for group %d
\n
"
,
i
);
}
printk
(
"group %d: stored = %d, counted = %lu
\n
"
,
i
,
gdp
[
desc
].
bg_free_blocks_count
,
x
);
i
,
gdp
->
bg_free_blocks_count
,
x
);
bitmap_count
+=
x
;
desc
++
;
if
(
desc
==
EXT2_DESC_PER_BLOCK
(
sb
))
{
group_desc
++
;
desc
=
0
;
gdp
=
NULL
;
}
}
printk
(
"ext2_count_free_blocks: stored = %lu, computed = %lu, %lu
\n
"
,
es
->
s_free_blocks_count
,
desc_count
,
bitmap_count
);
...
...
@@ -570,57 +587,57 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
#endif
}
static
inline
int
block_in_use
(
unsigned
long
block
,
struct
super_block
*
sb
,
unsigned
char
*
map
)
{
return
test_bit
((
block
-
sb
->
u
.
ext2_sb
.
s_es
->
s_first_data_block
)
%
EXT2_BLOCKS_PER_GROUP
(
sb
),
map
);
}
void
ext2_check_blocks_bitmap
(
struct
super_block
*
sb
)
{
struct
buffer_head
*
bh
;
struct
ext2_super_block
*
es
;
unsigned
long
desc_count
,
bitmap_count
,
x
;
unsigned
long
group_desc
;
unsigned
long
desc
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
int
i
;
int
i
,
j
;
lock_super
(
sb
);
es
=
sb
->
u
.
ext2_sb
.
s_es
;
desc_count
=
0
;
bitmap_count
=
0
;
group_desc
=
0
;
desc
=
0
;
gdp
=
NULL
;
for
(
i
=
0
;
i
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
i
++
)
{
if
(
!
gdp
)
{
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
])
{
gdp
=
get_group_desc
(
sb
,
i
,
NULL
);
desc_count
+=
gdp
->
bg_free_blocks_count
;
bitmap_nr
=
load_block_bitmap
(
sb
,
i
);
bh
=
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
];
if
(
!
block_in_use
(
gdp
->
bg_block_bitmap
,
sb
,
bh
->
b_data
))
ext2_error
(
sb
,
"ext2_check_blocks_bitmap"
,
"Descriptor not loaded for group %d
"
,
"Block bitmap for group %d is marked free
"
,
i
);
break
;
}
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
}
desc_count
+=
gdp
[
desc
].
bg_free_blocks_count
;
bitmap_nr
=
load_block_bitmap
(
sb
,
i
);
if
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
])
x
=
ext2_count_free
(
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
bitmap_nr
],
sb
->
s_blocksize
);
else
{
x
=
0
;
if
(
!
block_in_use
(
gdp
->
bg_inode_bitmap
,
sb
,
bh
->
b_data
))
ext2_error
(
sb
,
"ext2_check_blocks_bitmap"
,
"Cannot load bitmap for group %d
\n
"
,
i
);
}
if
(
gdp
[
desc
].
bg_free_blocks_count
!=
x
)
"Inode bitmap for group %d is marked free"
,
i
);
for
(
j
=
0
;
j
<
sb
->
u
.
ext2_sb
.
s_itb_per_group
;
j
++
)
if
(
!
block_in_use
(
gdp
->
bg_inode_table
+
j
,
sb
,
bh
->
b_data
))
ext2_error
(
sb
,
"ext2_check_blocks_bitmap"
,
"Block #%d of the inode table in group %d "
"is marked free"
,
j
,
i
);
x
=
ext2_count_free
(
bh
,
sb
->
s_blocksize
);
if
(
gdp
->
bg_free_blocks_count
!=
x
)
ext2_error
(
sb
,
"ext2_check_blocks_bitmap"
,
"Wrong free blocks count for group %d, "
"stored = %d, counted = %lu"
,
i
,
gdp
[
desc
].
bg_free_blocks_count
,
x
);
gdp
->
bg_free_blocks_count
,
x
);
bitmap_count
+=
x
;
desc
++
;
if
(
desc
==
EXT2_DESC_PER_BLOCK
(
sb
))
{
group_desc
++
;
desc
=
0
;
gdp
=
NULL
;
}
}
if
(
es
->
s_free_blocks_count
!=
bitmap_count
)
ext2_error
(
sb
,
"ext2_check_blocks_bitmap"
,
...
...
fs/ext2/bitmap.c
View file @
c6145b38
/*
* linux/fs/ext2/bitmap.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*/
#include <linux/fs.h>
...
...
fs/ext2/dcache.c
View file @
c6145b38
/*
* linux/fs/ext2/dcache.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
*/
...
...
@@ -14,7 +16,6 @@
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/string.h>
#ifndef DONT_USE_DCACHE
...
...
fs/ext2/dir.c
View file @
c6145b38
/*
* linux/fs/ext2/dir.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -14,26 +16,32 @@
#include <asm/segment.h>
#include <linux/autoconf.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/sched.h>
#include <linux/stat.h>
#if
0
#if
ndef CONFIG_EXT2_FS_DIR_READ
static
int
ext2_dir_read
(
struct
inode
*
inode
,
struct
file
*
filp
,
char
*
buf
,
int
count
)
{
return
-
EISDIR
;
}
#else
int
ext2_file_read
(
struct
inode
*
,
struct
file
*
,
char
*
,
int
);
#endif
/* static */
int
ext2_file_read
(
struct
inode
*
,
struct
file
*
,
char
*
,
int
);
static
int
ext2_readdir
(
struct
inode
*
,
struct
file
*
,
struct
dirent
*
,
int
);
static
struct
file_operations
ext2_dir_operations
=
{
NULL
,
/* lseek - default */
#ifdef CONFIG_EXT2_FS_DIR_READ
ext2_file_read
,
/* read */
#else
ext2_dir_read
,
/* read */
#endif
NULL
,
/* write - bad */
ext2_readdir
,
/* readdir */
NULL
,
/* select - default */
...
...
@@ -92,9 +100,9 @@ int ext2_check_dir_entry (char * function, struct inode * dir,
static
int
ext2_readdir
(
struct
inode
*
inode
,
struct
file
*
filp
,
struct
dirent
*
dirent
,
int
count
)
{
unsigned
long
offset
;
int
i
;
struct
buffer_head
*
bh
;
unsigned
long
offset
,
blk
;
int
i
,
num
;
struct
buffer_head
*
bh
,
*
tmp
,
*
bha
[
16
]
;
struct
ext2_dir_entry
*
de
;
struct
super_block
*
sb
;
int
err
;
...
...
@@ -104,15 +112,35 @@ static int ext2_readdir (struct inode * inode, struct file * filp,
sb
=
inode
->
i_sb
;
while
(
filp
->
f_pos
<
inode
->
i_size
)
{
offset
=
filp
->
f_pos
&
(
sb
->
s_blocksize
-
1
);
b
h
=
ext2_bread
(
inode
,
(
filp
->
f_pos
)
>>
EXT2_BLOCK_SIZE_BITS
(
sb
),
0
,
&
err
);
b
lk
=
(
filp
->
f_pos
)
>>
EXT2_BLOCK_SIZE_BITS
(
sb
);
bh
=
ext2_bread
(
inode
,
blk
,
0
,
&
err
);
if
(
!
bh
)
{
filp
->
f_pos
+=
sb
->
s_blocksize
-
offset
;
continue
;
}
/*
* Do the readahead
*/
if
(
!
offset
)
{
for
(
i
=
16
>>
(
EXT2_BLOCK_SIZE_BITS
(
sb
)
-
9
),
num
=
0
;
i
>
0
;
i
--
)
{
tmp
=
ext2_getblk
(
inode
,
++
blk
,
0
,
&
err
);
if
(
tmp
&&
!
tmp
->
b_uptodate
&&
!
tmp
->
b_lock
)
bha
[
num
++
]
=
tmp
;
else
brelse
(
tmp
);
}
if
(
num
)
{
ll_rw_block
(
READA
,
num
,
bha
);
for
(
i
=
0
;
i
<
num
;
i
++
)
brelse
(
bha
[
i
]);
}
}
de
=
(
struct
ext2_dir_entry
*
)
(
offset
+
bh
->
b_data
);
while
(
offset
<
sb
->
s_blocksize
&&
filp
->
f_pos
<
inode
->
i_size
)
{
if
(
!
ext2_check_dir_entry
(
"ext2_readdir"
,
inode
,
de
,
if
(
!
ext2_check_dir_entry
(
"ext2_readdir"
,
inode
,
de
,
bh
,
offset
))
{
brelse
(
bh
);
return
0
;
...
...
fs/ext2/file.c
View file @
c6145b38
/*
* linux/fs/ext2/file.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -15,11 +17,11 @@
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/autoconf.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/fcntl.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/locks.h>
...
...
@@ -32,8 +34,12 @@
#include <linux/fs.h>
#include <linux/ext2_fs.h>
/* static */
int
ext2_file_read
(
struct
inode
*
,
struct
file
*
,
char
*
,
int
);
#ifndef CONFIG_EXT2_FS_DIR_READ
static
#endif
int
ext2_file_read
(
struct
inode
*
,
struct
file
*
,
char
*
,
int
);
static
int
ext2_file_write
(
struct
inode
*
,
struct
file
*
,
char
*
,
int
);
static
void
ext2_release_file
(
struct
inode
*
,
struct
file
*
);
/*
* We have mostly NULL's here: the current defaults are ok for
...
...
@@ -48,7 +54,7 @@ static struct file_operations ext2_file_operations = {
ext2_ioctl
,
/* ioctl */
generic_mmap
,
/* mmap */
NULL
,
/* no special open is needed */
NULL
,
/* release */
ext2_release_file
,
/* release */
ext2_sync_file
/* fsync */
};
...
...
@@ -70,7 +76,10 @@ struct inode_operations ext2_file_inode_operations = {
ext2_permission
/* permission */
};
/* static */
int
ext2_file_read
(
struct
inode
*
inode
,
struct
file
*
filp
,
#ifndef CONFIG_EXT2_FS_DIR_READ
static
#endif
int
ext2_file_read
(
struct
inode
*
inode
,
struct
file
*
filp
,
char
*
buf
,
int
count
)
{
int
read
,
left
,
chars
;
...
...
@@ -116,15 +125,17 @@ struct inode_operations ext2_file_inode_operations = {
blocks
=
size
-
block
;
}
/* We do this in a two stage process. We first try and request
as many blocks as we can, then we wait for the first one to
complete, and then we try and 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. */
/*
* We do this in a two stage process. We first try and request
* as many blocks as we can, then we wait for the first one to
* complete, and then we try and 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
;
...
...
@@ -140,8 +151,10 @@ struct inode_operations ext2_file_inode_operations = {
if
(
++
bhb
==
&
buflist
[
NBUF
])
bhb
=
buflist
;
/* If the block we have on hand is uptodate, go ahead
and complete processing */
/*
* If the block we have on hand is uptodate, go ahead
* and complete processing
*/
if
(
uptodate
)
break
;
...
...
@@ -149,11 +162,16 @@ struct inode_operations ext2_file_inode_operations = {
break
;
}
/* Now request them all */
/*
* Now request them all
*/
if
(
bhrequest
)
ll_rw_block
(
READ
,
bhrequest
,
bhreq
);
do
{
/* Finish off all I/O that has actually completed */
do
{
/*
* Finish off all I/O that has actually completed
*/
if
(
*
bhe
)
{
wait_on_buffer
(
*
bhe
);
if
(
!
(
*
bhe
)
->
b_uptodate
)
{
/* read error? */
...
...
@@ -186,7 +204,9 @@ struct inode_operations ext2_file_inode_operations = {
}
while
(
left
>
0
&&
bhe
!=
bhb
&&
(
!*
bhe
||
!
(
*
bhe
)
->
b_lock
));
}
while
(
left
>
0
);
/* Release the read-ahead blocks */
/*
* Release the read-ahead blocks
*/
while
(
bhe
!=
bhb
)
{
brelse
(
*
bhe
);
if
(
++
bhe
==
&
buflist
[
NBUF
])
...
...
@@ -217,6 +237,12 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
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
))
{
ext2_warning
(
sb
,
"ext2_file_write"
,
"mode = %07o
\n
"
,
inode
->
i_mode
);
...
...
@@ -269,3 +295,14 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
inode
->
i_dirt
=
1
;
return
written
;
}
/*
* Called when a inode is released. Note that this is different
* from ext2_open: open gets called at every open, but release
* gets called only when /all/ the files are closed.
*/
static
void
ext2_release_file
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
if
(
filp
->
f_mode
&
2
)
ext2_discard_prealloc
(
inode
);
}
fs/ext2/fsync.c
View file @
c6145b38
...
...
@@ -4,6 +4,8 @@
* Copyright (C) 1993 Stephen Tweedie (sct@dcs.ed.ac.uk)
* from
* Copyright (C) 1992 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
* from
* linux/fs/minix/truncate.c Copyright (C) 1991, 1992 Linus Torvalds
*
...
...
@@ -171,8 +173,10 @@ int ext2_sync_file (struct inode * inode, struct file * file)
if
(
!
(
S_ISREG
(
inode
->
i_mode
)
||
S_ISDIR
(
inode
->
i_mode
)
||
S_ISLNK
(
inode
->
i_mode
)))
return
-
EINVAL
;
/* Don't sync fast links! */
if
(
S_ISLNK
(
inode
->
i_mode
)
&&
!
(
inode
->
i_blocks
))
/*
* Don't sync fast links!
*/
goto
skip
;
for
(
wait
=
0
;
wait
<=
1
;
wait
++
)
...
...
fs/ext2/ialloc.c
View file @
c6145b38
/*
* linux/fs/ext2/ialloc.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* BSD ufs-inspired inode and directory allocation by
* Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
*/
/* ialloc.c contains the inodes allocation and deallocation routines */
/*
* ialloc.c contains the inodes allocation and deallocation routines
*/
The free inodes are managed by bitmaps. A file system contains several
blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
block for inodes, N blocks for the inode table and data blocks.
The file system contains group descriptors which are located after the
super block. Each descriptor contains the number of the bitmap block and
the free blocks count in the block. The descriptors are loaded in memory
when a file system is mounted (see ext2_read_super).
*/
/*
* The free inodes are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* block for inodes, N blocks for the inode table and data blocks.
*
* The file system contains group descriptors which are located after the
* super block. Each descriptor contains the number of the bitmap block and
* the free blocks count in the block. The descriptors are loaded in memory
* when a file system is mounted (see ext2_read_super).
*/
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/string.h>
...
...
@@ -59,28 +59,47 @@ static inline int find_first_zero_bit (unsigned long * addr, unsigned size)
return
res
;
}
static
void
read_inode_bitmap
(
struct
super_block
*
sb
,
unsigned
long
block_group
,
unsigned
int
bitmap_nr
)
static
struct
ext2_group_desc
*
get_group_desc
(
struct
super_block
*
sb
,
unsigned
int
block_group
,
struct
buffer_head
**
bh
)
{
unsigned
long
group_desc
;
unsigned
long
desc
;
struct
ext2_group_desc
*
gdp
;
struct
buffer_head
*
bh
;
if
(
block_group
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
ext2_panic
(
sb
,
"get_group_desc"
,
"block_group >= groups_count
\n
"
"block_group = %d, groups_count = %lu"
,
block_group
,
sb
->
u
.
ext2_sb
.
s_groups_count
);
group_desc
=
block_group
/
EXT2_DESC_PER_BLOCK
(
sb
);
desc
=
block_group
%
EXT2_DESC_PER_BLOCK
(
sb
);
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
])
ext2_panic
(
sb
,
"
read_inode_bitmap
"
,
ext2_panic
(
sb
,
"
get_group_desc
"
,
"Group descriptor not loaded
\n
"
"block_group = %
lu
, group_desc = %lu, desc = %lu"
,
"block_group = %
d
, group_desc = %lu, desc = %lu"
,
block_group
,
group_desc
,
desc
);
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
bh
=
bread
(
sb
->
s_dev
,
gdp
[
desc
].
bg_inode_bitmap
,
sb
->
s_blocksize
);
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
if
(
bh
)
*
bh
=
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
];
return
gdp
+
desc
;
}
static
void
read_inode_bitmap
(
struct
super_block
*
sb
,
unsigned
long
block_group
,
unsigned
int
bitmap_nr
)
{
struct
ext2_group_desc
*
gdp
;
struct
buffer_head
*
bh
;
gdp
=
get_group_desc
(
sb
,
block_group
,
NULL
);
bh
=
bread
(
sb
->
s_dev
,
gdp
->
bg_inode_bitmap
,
sb
->
s_blocksize
);
if
(
!
bh
)
ext2_panic
(
sb
,
"read_inode_bitmap"
,
"Cannot read inode bitmap
\n
"
"block_group = %lu,
group_desc = %lu, desc = %lu,
inode_bitmap = %lu"
,
block_group
,
g
roup_desc
,
desc
,
gdp
[
desc
].
bg_inode_bitmap
);
"block_group = %lu, inode_bitmap = %lu"
,
block_group
,
g
dp
->
bg_inode_bitmap
);
sb
->
u
.
ext2_sb
.
s_inode_bitmap_number
[
bitmap_nr
]
=
block_group
;
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
]
=
bh
;
}
...
...
@@ -162,13 +181,13 @@ static int load_inode_bitmap (struct super_block * sb,
* This may be used one day by an 'undelete' program
*/
static
void
set_inode_dtime
(
struct
inode
*
inode
,
struct
ext2_group_desc
*
gdp
,
unsigned
long
desc
)
struct
ext2_group_desc
*
gdp
)
{
unsigned
long
inode_block
;
struct
buffer_head
*
bh
;
struct
ext2_inode
*
raw_inode
;
inode_block
=
gdp
[
desc
].
bg_inode_table
+
(((
inode
->
i_ino
-
1
)
%
inode_block
=
gdp
->
bg_inode_table
+
(((
inode
->
i_ino
-
1
)
%
EXT2_INODES_PER_GROUP
(
inode
->
i_sb
))
/
EXT2_INODES_PER_BLOCK
(
inode
->
i_sb
));
bh
=
bread
(
inode
->
i_sb
->
s_dev
,
inode_block
,
inode
->
i_sb
->
s_blocksize
);
...
...
@@ -198,8 +217,6 @@ void ext2_free_inode (struct inode * inode)
struct
buffer_head
*
bh2
;
unsigned
long
block_group
;
unsigned
long
bit
;
unsigned
long
group_desc
;
unsigned
long
desc
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
struct
ext2_super_block
*
es
;
...
...
@@ -241,28 +258,18 @@ void ext2_free_inode (struct inode * inode)
bit
=
(
inode
->
i_ino
-
1
)
%
EXT2_INODES_PER_GROUP
(
sb
);
bitmap_nr
=
load_inode_bitmap
(
sb
,
block_group
);
bh
=
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
];
if
(
!
bh
)
ext2_panic
(
sb
,
"ext2_free_inode"
,
"Unable to load bitmap for group %lu"
,
block_group
);
if
(
!
clear_bit
(
bit
,
bh
->
b_data
))
ext2_warning
(
sb
,
"ext2_free_inode"
,
"bit already cleared for inode %lu"
,
inode
->
i_ino
);
else
{
group_desc
=
block_group
/
EXT2_DESC_PER_BLOCK
(
sb
);
desc
=
block_group
%
EXT2_DESC_PER_BLOCK
(
sb
);
bh2
=
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
];
if
(
!
bh2
)
ext2_panic
(
sb
,
"ext2_free_inode"
,
"Group descriptor not loaded for group %lu"
,
group_desc
);
gdp
=
(
struct
ext2_group_desc
*
)
bh2
->
b_data
;
gdp
[
desc
].
bg_free_inodes_count
++
;
gdp
=
get_group_desc
(
sb
,
block_group
,
&
bh2
);
gdp
->
bg_free_inodes_count
++
;
if
(
S_ISDIR
(
inode
->
i_mode
))
gdp
[
desc
].
bg_used_dirs_count
--
;
gdp
->
bg_used_dirs_count
--
;
bh2
->
b_dirt
=
1
;
es
->
s_free_inodes_count
++
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
set_inode_dtime
(
inode
,
gdp
,
desc
);
set_inode_dtime
(
inode
,
gdp
);
}
bh
->
b_dirt
=
1
;
if
(
sb
->
s_flags
&
MS_SYNC
)
{
...
...
@@ -310,22 +317,6 @@ static void inc_inode_version (struct inode * inode,
brelse
(
bh
);
}
static
struct
ext2_group_desc
*
get_group_desc
(
struct
super_block
*
sb
,
int
group
)
{
struct
ext2_group_desc
*
gdp
;
if
(
group
>=
sb
->
u
.
ext2_sb
.
s_groups_count
||
group
<
0
)
ext2_panic
(
sb
,
"get_group_desc"
,
"Invalid group %d"
,
group
);
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group
/
EXT2_DESC_PER_BLOCK
(
sb
)])
ext2_panic
(
sb
,
"get_group_desc"
,
"Descriptor not loaded for group %d"
,
group
);
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group
/
EXT2_DESC_PER_BLOCK
(
sb
)]
->
b_data
;
return
gdp
+
(
group
%
EXT2_DESC_PER_BLOCK
(
sb
));
}
/*
* There are two policies for allocating an inode. If the new inode is
* a directory, then a forward search is made for a block group with both
...
...
@@ -340,10 +331,12 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
{
struct
super_block
*
sb
;
struct
buffer_head
*
bh
;
struct
buffer_head
*
bh2
;
int
i
,
j
,
avefreei
;
struct
inode
*
inode
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
,
*
tmp
;
struct
ext2_group_desc
*
gdp
;
struct
ext2_group_desc
*
tmp
;
struct
ext2_super_block
*
es
;
if
(
!
dir
||
!
(
inode
=
get_empty_inode
()))
...
...
@@ -362,7 +355,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
/* I am not yet convinced that this next bit is necessary.
i = dir->u.ext2_i.i_block_group;
for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
tmp = get_group_desc (sb, i);
tmp = get_group_desc (sb, i
, &bh2
);
if ((tmp->bg_used_dirs_count << 8) <
tmp->bg_free_inodes_count) {
gdp = tmp;
...
...
@@ -374,12 +367,12 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
*/
if
(
!
gdp
)
{
for
(
j
=
0
;
j
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
j
++
)
{
tmp
=
get_group_desc
(
sb
,
j
);
tmp
=
get_group_desc
(
sb
,
j
,
&
bh2
);
if
(
tmp
->
bg_free_inodes_count
&&
tmp
->
bg_free_inodes_count
>=
avefreei
)
{
if
(
!
gdp
||
(
tmp
->
bg_free_
inode
s_count
>
gdp
->
bg_free_
inode
s_count
))
{
(
tmp
->
bg_free_
block
s_count
>
gdp
->
bg_free_
block
s_count
))
{
i
=
j
;
gdp
=
tmp
;
}
...
...
@@ -388,18 +381,25 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
}
}
else
{
/* Try to place the inode in it\'s parent directory */
{
/*
* Try to place the inode in it's parent directory
*/
i
=
dir
->
u
.
ext2_i
.
i_block_group
;
tmp
=
get_group_desc
(
sb
,
i
);
tmp
=
get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
tmp
->
bg_free_inodes_count
)
gdp
=
tmp
;
else
{
/* Use a quadratic hash to find a group with a free inode */
{
/*
* Use a quadratic hash to find a group with a
* free inode
*/
for
(
j
=
1
;
j
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
j
<<=
1
)
{
i
+=
j
;
if
(
i
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
i
-=
sb
->
u
.
ext2_sb
.
s_groups_count
;
tmp
=
get_group_desc
(
sb
,
i
);
tmp
=
get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
tmp
->
bg_free_inodes_count
)
{
gdp
=
tmp
;
break
;
...
...
@@ -407,12 +407,14 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
}
}
if
(
!
gdp
)
{
/* That failed: try linear search for a free inode */
/*
* That failed: try linear search for a free inode
*/
i
=
dir
->
u
.
ext2_i
.
i_block_group
+
2
;
for
(
j
=
2
;
j
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
j
++
)
{
if
(
++
i
>=
sb
->
u
.
ext2_sb
.
s_groups_count
)
i
=
0
;
tmp
=
get_group_desc
(
sb
,
i
);
tmp
=
get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
tmp
->
bg_free_inodes_count
)
{
gdp
=
tmp
;
break
;
...
...
@@ -428,9 +430,6 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
}
bitmap_nr
=
load_inode_bitmap
(
sb
,
i
);
bh
=
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
];
if
(
!
bh
)
ext2_panic
(
sb
,
"ext2_new_inode"
,
"Unable to load bitmap for group %d"
,
i
);
if
((
j
=
find_first_zero_bit
((
unsigned
long
*
)
bh
->
b_data
,
EXT2_INODES_PER_GROUP
(
sb
)))
<
EXT2_INODES_PER_GROUP
(
sb
))
{
...
...
@@ -447,9 +446,9 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
}
else
goto
repeat
;
j
+=
i
*
EXT2_INODES_PER_GROUP
(
sb
)
+
1
;
if
(
j
>
es
->
s_inodes_count
)
{
if
(
j
<
EXT2_FIRST_INO
||
j
>
es
->
s_inodes_count
)
{
ext2_error
(
sb
,
"ext2_new_inode"
,
"inode > inodes count
\n
"
"
reserved inode or
inode > inodes count
\n
"
"block_group = %d,inode=%d"
,
i
,
j
);
unlock_super
(
sb
);
iput
(
inode
);
...
...
@@ -458,7 +457,7 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
gdp
->
bg_free_inodes_count
--
;
if
(
S_ISDIR
(
mode
))
gdp
->
bg_used_dirs_count
++
;
sb
->
u
.
ext2_sb
.
s_group_desc
[
i
/
EXT2_DESC_PER_BLOCK
(
sb
)]
->
b_dirt
=
1
;
bh2
->
b_dirt
=
1
;
es
->
s_free_inodes_count
--
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
sb
->
s_dirt
=
1
;
...
...
@@ -468,7 +467,10 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode)
inode
->
i_nlink
=
1
;
inode
->
i_dev
=
sb
->
s_dev
;
inode
->
i_uid
=
current
->
euid
;
inode
->
i_gid
=
(
dir
->
i_mode
&
S_ISGID
)
?
dir
->
i_gid
:
current
->
egid
;
if
((
dir
->
i_mode
&
S_ISGID
)
||
test_opt
(
sb
,
GRPID
))
inode
->
i_gid
=
dir
->
i_gid
;
else
inode
->
i_gid
=
current
->
egid
;
inode
->
i_dirt
=
1
;
inode
->
i_ino
=
j
;
inode
->
i_blksize
=
sb
->
s_blocksize
;
...
...
@@ -499,8 +501,6 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
#ifdef EXT2FS_DEBUG
struct
ext2_super_block
*
es
;
unsigned
long
desc_count
,
bitmap_count
,
x
;
unsigned
long
group_desc
;
unsigned
long
desc
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
int
i
;
...
...
@@ -509,36 +509,16 @@ unsigned long ext2_count_free_inodes (struct super_block * sb)
es
=
sb
->
u
.
ext2_sb
.
s_es
;
desc_count
=
0
;
bitmap_count
=
0
;
group_desc
=
0
;
desc
=
0
;
gdp
=
NULL
;
for
(
i
=
0
;
i
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
i
++
)
{
if
(
!
gdp
)
{
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
])
{
printk
(
"ext2_count_free_inodes: Descriptor not loaded
\n
"
);
break
;
}
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
}
desc_count
+=
gdp
[
desc
].
bg_free_inodes_count
;
gdp
=
get_group_desc
(
sb
,
i
,
NULL
);
desc_count
+=
gdp
->
bg_free_inodes_count
;
bitmap_nr
=
load_inode_bitmap
(
sb
,
i
);
if
(
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
])
x
=
ext2_count_free
(
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
],
EXT2_INODES_PER_GROUP
(
sb
)
/
8
);
else
{
x
=
0
;
printk
(
"Cannot load inode bitmap for group %d (bitmap = %d)
\n
"
,
i
,
bitmap_nr
);
}
printk
(
"group %d: stored = %d, counted = %lu
\n
"
,
i
,
gdp
[
desc
].
bg_free_inodes_count
,
x
);
i
,
gdp
->
bg_free_inodes_count
,
x
);
bitmap_count
+=
x
;
desc
++
;
if
(
desc
==
EXT2_DESC_PER_BLOCK
(
sb
))
{
group_desc
++
;
desc
=
0
;
gdp
=
NULL
;
}
}
printk
(
"ext2_count_free_inodes: stored = %lu, computed = %lu, %lu
\n
"
,
es
->
s_free_inodes_count
,
desc_count
,
bitmap_count
);
...
...
@@ -553,8 +533,6 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
{
struct
ext2_super_block
*
es
;
unsigned
long
desc_count
,
bitmap_count
,
x
;
unsigned
long
group_desc
;
unsigned
long
desc
;
int
bitmap_nr
;
struct
ext2_group_desc
*
gdp
;
int
i
;
...
...
@@ -563,42 +541,19 @@ void ext2_check_inodes_bitmap (struct super_block * sb)
es
=
sb
->
u
.
ext2_sb
.
s_es
;
desc_count
=
0
;
bitmap_count
=
0
;
group_desc
=
0
;
desc
=
0
;
gdp
=
NULL
;
for
(
i
=
0
;
i
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
i
++
)
{
if
(
!
gdp
)
{
if
(
!
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
])
{
ext2_error
(
sb
,
"ext2_check_inodes_bitmap"
,
"Descriptor not loaded for group %d"
,
i
);
break
;
}
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
group_desc
]
->
b_data
;
}
desc_count
+=
gdp
[
desc
].
bg_free_inodes_count
;
gdp
=
get_group_desc
(
sb
,
i
,
NULL
);
desc_count
+=
gdp
->
bg_free_inodes_count
;
bitmap_nr
=
load_inode_bitmap
(
sb
,
i
);
if
(
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
])
x
=
ext2_count_free
(
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
bitmap_nr
],
EXT2_INODES_PER_GROUP
(
sb
)
/
8
);
else
{
x
=
0
;
ext2_error
(
sb
,
"ext2_check_inodes_bitmap"
,
"Cannot load bitmap for group %d (bitmap = %d)"
,
i
,
bitmap_nr
);
}
if
(
gdp
[
desc
].
bg_free_inodes_count
!=
x
)
if
(
gdp
->
bg_free_inodes_count
!=
x
)
ext2_error
(
sb
,
"ext2_check_inodes_bitmap"
,
"Wrong free inodes count in group %d, "
"stored = %d, counted = %lu"
,
i
,
gdp
[
desc
].
bg_free_inodes_count
,
x
);
gdp
->
bg_free_inodes_count
,
x
);
bitmap_count
+=
x
;
desc
++
;
if
(
desc
==
EXT2_DESC_PER_BLOCK
(
sb
))
{
group_desc
++
;
desc
=
0
;
gdp
=
NULL
;
}
}
if
(
es
->
s_free_inodes_count
!=
bitmap_count
)
ext2_error
(
sb
,
"ext2_check_inodes_bitmap"
,
...
...
fs/ext2/inode.c
View file @
c6145b38
/*
* linux/fs/ext2/inode.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -18,14 +20,22 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/locks.h>
#define clear_block(addr,size) \
__asm__("cld\n\t" \
"rep\n\t" \
"stosl" \
: \
:"a" (0), "c" (size / 4), "D" ((long) (addr)) \
:"cx", "di")
void
ext2_put_inode
(
struct
inode
*
inode
)
{
ext2_discard_prealloc
(
inode
);
if
(
inode
->
i_nlink
||
inode
->
i_ino
==
EXT2_ACL_IDX_INO
||
inode
->
i_ino
==
EXT2_ACL_DATA_INO
)
return
;
...
...
@@ -48,6 +58,78 @@ static int block_bmap (struct buffer_head * bh, int nr)
return
tmp
;
}
/*
* ext2_discard_prealloc and ext2_alloc_block are atomic wrt. the
* superblock in the same manner as are ext2_free_blocks and
* ext2_new_block. We just wait on the super rather than locking it
* here, since ext2_new_block will do the necessary locking and we
* can't block until then.
*/
void
ext2_discard_prealloc
(
struct
inode
*
inode
)
{
#ifdef EXT2_PREALLOCATE
if
(
inode
->
u
.
ext2_i
.
i_prealloc_count
)
{
ext2_free_blocks
(
inode
->
i_sb
,
inode
->
u
.
ext2_i
.
i_prealloc_block
,
inode
->
u
.
ext2_i
.
i_prealloc_count
);
inode
->
u
.
ext2_i
.
i_prealloc_count
=
0
;
}
#endif
}
static
int
ext2_alloc_block
(
struct
inode
*
inode
,
unsigned
long
goal
)
{
#ifdef EXT2FS_DEBUG
static
unsigned
long
alloc_hits
=
0
,
alloc_attempts
=
0
;
#endif
unsigned
long
result
;
struct
buffer_head
*
bh
;
wait_on_super
(
inode
->
i_sb
);
#ifdef EXT2_PREALLOCATE
if
(
inode
->
u
.
ext2_i
.
i_prealloc_count
&&
(
goal
==
inode
->
u
.
ext2_i
.
i_prealloc_block
||
goal
+
1
==
inode
->
u
.
ext2_i
.
i_prealloc_block
))
{
result
=
inode
->
u
.
ext2_i
.
i_prealloc_block
++
;
inode
->
u
.
ext2_i
.
i_prealloc_count
--
;
ext2_debug
(
"preallocation hit (%lu/%lu).
\n
"
,
++
alloc_hits
,
++
alloc_attempts
);
/* It doesn't matter if we block in getblk() since
we have already atomically allocated the block, and
are only clearing it now. */
if
(
!
(
bh
=
getblk
(
inode
->
i_sb
->
s_dev
,
result
,
inode
->
i_sb
->
s_blocksize
)))
{
ext2_error
(
inode
->
i_sb
,
"ext2_alloc_block"
,
"cannot get block %lu"
,
result
);
return
0
;
}
clear_block
(
bh
->
b_data
,
inode
->
i_sb
->
s_blocksize
);
bh
->
b_uptodate
=
1
;
bh
->
b_dirt
=
1
;
brelse
(
bh
);
}
else
{
ext2_discard_prealloc
(
inode
);
ext2_debug
(
"preallocation miss (%lu/%lu).
\n
"
,
alloc_hits
,
++
alloc_attempts
);
if
(
S_ISREG
(
inode
->
i_mode
))
result
=
ext2_new_block
(
inode
->
i_sb
,
goal
,
&
inode
->
u
.
ext2_i
.
i_prealloc_count
,
&
inode
->
u
.
ext2_i
.
i_prealloc_block
);
else
result
=
ext2_new_block
(
inode
->
i_sb
,
goal
,
0
,
0
);
}
#else
result
=
ext2_new_block
(
inode
->
i_sb
,
goal
,
0
,
0
);
#endif
return
result
;
}
int
ext2_bmap
(
struct
inode
*
inode
,
int
block
)
{
int
i
;
...
...
@@ -147,12 +229,12 @@ static struct buffer_head * inode_getblk (struct inode * inode, int nr,
ext2_debug
(
"goal = %d.
\n
"
,
goal
);
tmp
=
ext2_
new_block
(
inode
->
i_sb
,
goal
);
tmp
=
ext2_
alloc_block
(
inode
,
goal
);
if
(
!
tmp
)
return
NULL
;
result
=
getblk
(
inode
->
i_dev
,
tmp
,
inode
->
i_sb
->
s_blocksize
);
if
(
*
p
)
{
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
brelse
(
result
);
goto
repeat
;
}
...
...
@@ -219,14 +301,14 @@ static struct buffer_head * block_getblk (struct inode * inode,
if
(
!
goal
)
goal
=
bh
->
b_blocknr
+
1
;
}
tmp
=
ext2_
new_block
(
inode
->
i_sb
,
goal
);
tmp
=
ext2_
alloc_block
(
inode
,
goal
);
if
(
!
tmp
)
{
brelse
(
bh
);
return
NULL
;
}
result
=
getblk
(
bh
->
b_dev
,
tmp
,
blocksize
);
if
(
*
p
)
{
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
brelse
(
result
);
goto
repeat
;
}
...
...
@@ -263,9 +345,11 @@ struct buffer_head * ext2_getblk (struct inode * inode, long block,
ext2_warning
(
inode
->
i_sb
,
"ext2_getblk"
,
"block > big"
);
return
NULL
;
}
/* If this is a sequential block allocation, set the next_alloc_block
to this block now so that all the indblock and data block
allocations use the same goal zone */
/*
* If this is a sequential block allocation, set the next_alloc_block
* to this block now so that all the indblock and data block
* allocations use the same goal zone
*/
ext2_debug
(
"block %lu, next %lu, goal %lu.
\n
"
,
block
,
inode
->
u
.
ext2_i
.
i_next_alloc_block
,
...
...
@@ -379,6 +463,9 @@ void ext2_read_inode (struct inode * inode)
inode
->
u
.
ext2_i
.
i_block_group
=
block_group
;
inode
->
u
.
ext2_i
.
i_next_alloc_block
=
0
;
inode
->
u
.
ext2_i
.
i_next_alloc_goal
=
0
;
if
(
inode
->
u
.
ext2_i
.
i_prealloc_count
)
ext2_error
(
inode
->
i_sb
,
"ext2_read_inode"
,
"New inode has non-zero prealloc count!"
);
if
(
S_ISCHR
(
inode
->
i_mode
)
||
S_ISBLK
(
inode
->
i_mode
))
inode
->
i_rdev
=
raw_inode
->
i_block
[
0
];
else
for
(
block
=
0
;
block
<
EXT2_N_BLOCKS
;
block
++
)
...
...
fs/ext2/ioctl.c
View file @
c6145b38
/*
* linux/fs/ext2/ioctl.c
*
* Copyright (C) 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*/
#include <asm/segment.h>
...
...
fs/ext2/namei.c
View file @
c6145b38
/*
* linux/fs/ext2/namei.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -16,7 +18,6 @@
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/fcntl.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/string.h>
...
...
@@ -28,6 +29,14 @@
*/
/* #define NO_TRUNCATE */
/*
* define how far ahead to read directories while searching them.
*/
#define NAMEI_RA_CHUNKS 2
#define NAMEI_RA_BLOCKS 4
#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
/*
* NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
*/
...
...
@@ -38,7 +47,9 @@ static int ext2_match (int len, const char * const name,
if
(
!
de
||
!
de
->
inode
||
len
>
EXT2_NAME_LEN
)
return
0
;
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
/*
* "" means "." ---> so paths like "/usr/lib//libc.a" work
*/
if
(
!
len
&&
de
->
name_len
==
1
&&
(
de
->
name
[
0
]
==
'.'
)
&&
(
de
->
name
[
1
]
==
'\0'
))
return
1
;
...
...
@@ -60,22 +71,22 @@ static int ext2_match (int len, const char * const name,
* returns the cache buffer in which the entry was found, and the entry
* itself (as a parameter - res_dir). It does NOT read the inode of the
* entry - you'll have to do that yourself if you want to.
*
*/
static
struct
buffer_head
*
ext2_find_entry
(
struct
inode
*
dir
,
const
char
*
const
name
,
int
namelen
,
struct
ext2_dir_entry
**
res_dir
)
{
unsigned
long
offset
;
struct
buffer_head
*
bh
;
struct
ext2_dir_entry
*
de
;
struct
super_block
*
sb
;
int
err
;
struct
buffer_head
*
bh_use
[
NAMEI_RA_SIZE
];
struct
buffer_head
*
bh_read
[
NAMEI_RA_SIZE
];
unsigned
long
offset
;
int
block
,
toread
,
i
,
err
;
*
res_dir
=
NULL
;
if
(
!
dir
)
return
NULL
;
sb
=
dir
->
i_sb
;
#ifdef NO_TRUNCATE
if
(
namelen
>
EXT2_NAME_LEN
)
return
NULL
;
...
...
@@ -83,34 +94,76 @@ static struct buffer_head * ext2_find_entry (struct inode * dir,
if
(
namelen
>
EXT2_NAME_LEN
)
namelen
=
EXT2_NAME_LEN
;
#endif
bh
=
ext2_bread
(
dir
,
0
,
0
,
&
err
);
if
(
!
bh
)
return
NULL
;
memset
(
bh_use
,
0
,
sizeof
(
bh_use
));
toread
=
0
;
for
(
block
=
0
;
block
<
NAMEI_RA_SIZE
;
++
block
)
{
struct
buffer_head
*
bh
;
if
((
block
<<
EXT2_BLOCK_SIZE_BITS
(
sb
))
>=
dir
->
i_size
)
break
;
bh
=
ext2_getblk
(
dir
,
block
,
0
,
&
err
);
bh_use
[
block
]
=
bh
;
if
(
bh
&&
!
bh
->
b_uptodate
)
bh_read
[
toread
++
]
=
bh
;
}
block
=
0
;
offset
=
0
;
de
=
(
struct
ext2_dir_entry
*
)
bh
->
b_data
;
while
(
offset
<
dir
->
i_size
)
{
if
(
!
bh
||
(
char
*
)
de
>=
sb
->
s_blocksize
+
bh
->
b_data
)
{
brelse
(
bh
);
bh
=
ext2_bread
(
dir
,
offset
>>
EXT2_BLOCK_SIZE_BITS
(
sb
),
0
,
&
err
);
if
(
!
bh
)
{
offset
+=
sb
->
s_blocksize
;
continue
;
}
de
=
(
struct
ext2_dir_entry
*
)
bh
->
b_data
;
struct
buffer_head
*
bh
;
struct
ext2_dir_entry
*
de
;
char
*
dlimit
;
if
((
block
%
NAMEI_RA_BLOCKS
)
==
0
&&
toread
)
{
ll_rw_block
(
READ
,
toread
,
bh_read
);
toread
=
0
;
}
if
(
!
ext2_check_dir_entry
(
"ext2_find_entry"
,
dir
,
de
,
bh
,
offset
))
{
brelse
(
bh
);
return
NULL
;
bh
=
bh_use
[
block
%
NAMEI_RA_SIZE
];
if
(
!
bh
)
ext2_panic
(
sb
,
"ext2_find_entry"
,
"buffer head pointer is NULL"
);
wait_on_buffer
(
bh
);
if
(
!
bh
->
b_uptodate
)
{
/*
* read error: all bets are off
*/
break
;
}
de
=
(
struct
ext2_dir_entry
*
)
bh
->
b_data
;
dlimit
=
bh
->
b_data
+
sb
->
s_blocksize
;
while
((
char
*
)
de
<
dlimit
)
{
if
(
!
ext2_check_dir_entry
(
"ext2_find_entry"
,
dir
,
de
,
bh
,
offset
))
goto
failure
;
if
(
de
->
inode
!=
0
&&
ext2_match
(
namelen
,
name
,
de
))
{
for
(
i
=
0
;
i
<
NAMEI_RA_SIZE
;
++
i
)
{
if
(
bh_use
[
i
]
!=
bh
)
brelse
(
bh_use
[
i
]);
}
*
res_dir
=
de
;
return
bh
;
}
offset
+=
de
->
rec_len
;
de
=
(
struct
ext2_dir_entry
*
)
((
char
*
)
de
+
de
->
rec_len
);
de
=
(
struct
ext2_dir_entry
*
)
((
char
*
)
de
+
de
->
rec_len
);
}
brelse
(
bh
);
if
(((
block
+
NAMEI_RA_SIZE
)
<<
EXT2_BLOCK_SIZE_BITS
(
sb
))
>=
dir
->
i_size
)
bh
=
NULL
;
else
bh
=
ext2_getblk
(
dir
,
block
+
NAMEI_RA_SIZE
,
0
,
&
err
);
bh_use
[
block
++
%
NAMEI_RA_SIZE
]
=
bh
;
if
(
bh
&&
!
bh
->
b_uptodate
)
bh_read
[
toread
++
]
=
bh
;
}
failure:
for
(
i
=
0
;
i
<
NAMEI_RA_SIZE
;
++
i
)
brelse
(
bh_use
[
i
]);
return
NULL
;
}
...
...
@@ -187,8 +240,9 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
#endif
if
(
!
namelen
)
return
NULL
;
/* Is this a busy deleted directory? Can't create new files
if so */
/*
* Is this a busy deleted directory? Can't create new files if so
*/
if
(
dir
->
i_size
==
0
)
{
*
err
=
-
ENOENT
;
...
...
@@ -231,7 +285,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
de
=
(
struct
ext2_dir_entry
*
)
bh
->
b_data
;
}
}
if
(
!
ext2_check_dir_entry
(
"ext2_add_entry"
,
dir
,
de
,
bh
,
if
(
!
ext2_check_dir_entry
(
"ext2_add_entry"
,
dir
,
de
,
bh
,
offset
))
{
*
err
=
-
ENOENT
;
brelse
(
bh
);
...
...
@@ -295,13 +349,12 @@ static int ext2_delete_entry (struct ext2_dir_entry * dir,
pde
=
NULL
;
de
=
(
struct
ext2_dir_entry
*
)
bh
->
b_data
;
while
(
i
<
bh
->
b_size
)
{
if
(
!
ext2_check_dir_entry
(
"ext2_delete_entry"
,
NULL
,
if
(
!
ext2_check_dir_entry
(
"ext2_delete_entry"
,
NULL
,
de
,
bh
,
i
))
return
-
EIO
;
if
(
de
==
dir
)
{
if
(
pde
)
pde
->
rec_len
+=
dir
->
rec_len
;
/* XXX - must zero the inode number in every case !! */
dir
->
inode
=
0
;
return
0
;
}
...
...
@@ -548,7 +601,7 @@ static int empty_dir (struct inode * inode)
}
de
=
(
struct
ext2_dir_entry
*
)
bh
->
b_data
;
}
if
(
!
ext2_check_dir_entry
(
"empty_dir"
,
inode
,
de
,
bh
,
if
(
!
ext2_check_dir_entry
(
"empty_dir"
,
inode
,
de
,
bh
,
offset
))
{
brelse
(
bh
);
return
1
;
...
...
@@ -609,10 +662,13 @@ int ext2_rmdir (struct inode * dir, const char * name, int len)
goto
end_rmdir
;
}
if
(
inode
->
i_count
>
1
)
{
/* Are we deleting the last instance of a busy directory?
Better clean up if so. */
/* Make directory empty (it will be truncated when finally
dereferenced). This also inhibits ext2_add_entry. */
/*
* Are we deleting the last instance of a busy directory?
* Better clean up if so.
*
* Make directory empty (it will be truncated when finally
* dereferenced). This also inhibits ext2_add_entry.
*/
inode
->
i_size
=
0
;
}
retval
=
ext2_delete_entry
(
de
,
bh
);
...
...
@@ -969,14 +1025,18 @@ static int do_ext2_rename (struct inode * old_dir, const char * old_name,
&
retval
);
if
(
!
new_bh
)
goto
end_rename
;
/* sanity checking before doing the rename - avoid races */
/*
* sanity checking before doing the rename - avoid races
*/
if
(
new_inode
&&
(
new_de
->
inode
!=
new_inode
->
i_ino
))
goto
try_again
;
if
(
new_de
->
inode
&&
!
new_inode
)
goto
try_again
;
if
(
old_de
->
inode
!=
old_inode
->
i_ino
)
goto
try_again
;
/* ok, that's it */
/*
* ok, that's it
*/
new_de
->
inode
=
old_inode
->
i_ino
;
#ifndef DONT_USE_DCACHE
ext2_dcache_remove
(
old_dir
->
i_dev
,
old_dir
->
i_ino
,
old_de
->
name
,
...
...
fs/ext2/super.c
View file @
c6145b38
/*
* linux/fs/ext2/super.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -18,7 +20,6 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ext2_fs.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/string.h>
...
...
@@ -41,15 +42,22 @@ void ext2_error (struct super_block * sb, const char * function,
va_start
(
args
,
fmt
);
vsprintf
(
buf
,
fmt
,
args
);
va_end
(
args
);
printk
(
#ifdef KERN_ERR
KERN_ERR
#endif
"EXT2-fs error (device %d/%d): %s: %s
\n
"
,
if
(
test_opt
(
sb
,
ERRORS_PANIC
)
||
(
sb
->
u
.
ext2_sb
.
s_es
->
s_errors
==
EXT2_ERRORS_PANIC
&&
!
test_opt
(
sb
,
ERRORS_CONT
)
&&
!
test_opt
(
sb
,
ERRORS_RO
)))
panic
(
"EXT2-fs panic (device %d/%d): %s: %s
\n
"
,
MAJOR
(
sb
->
s_dev
),
MINOR
(
sb
->
s_dev
),
function
,
buf
);
printk
(
KERN_CRIT
"EXT2-fs error (device %d/%d): %s: %s
\n
"
,
MAJOR
(
sb
->
s_dev
),
MINOR
(
sb
->
s_dev
),
function
,
buf
);
if
(
test_opt
(
sb
,
ERRORS_RO
)
||
(
sb
->
u
.
ext2_sb
.
s_es
->
s_errors
==
EXT2_ERRORS_RO
&&
!
test_opt
(
sb
,
ERRORS_CONT
)
&&
!
test_opt
(
sb
,
ERRORS_PANIC
)))
{
printk
(
"Remounting filesystem read-only
\n
"
);
sb
->
s_flags
|=
MS_RDONLY
;
}
}
volatile
void
ext2_panic
(
struct
super_block
*
sb
,
const
char
*
function
,
NORET_TYPE
void
ext2_panic
(
struct
super_block
*
sb
,
const
char
*
function
,
const
char
*
fmt
,
...)
{
char
buf
[
1024
];
...
...
@@ -77,11 +85,7 @@ void ext2_warning (struct super_block * sb, const char * function,
va_start
(
args
,
fmt
);
vsprintf
(
buf
,
fmt
,
args
);
va_end
(
args
);
printk
(
#ifdef KERN_WARNING
KERN_WARNING
#endif
"EXT2-fs warning (device %d/%d): %s: %s
\n
"
,
printk
(
KERN_WARNING
"EXT2-fs warning (device %d/%d): %s: %s
\n
"
,
MAJOR
(
sb
->
s_dev
),
MINOR
(
sb
->
s_dev
),
function
,
buf
);
}
...
...
@@ -181,15 +185,75 @@ static int parse_options (char * options, unsigned long * sb_block,
this_char
=
strtok
(
NULL
,
","
))
{
if
((
value
=
strchr
(
this_char
,
'='
))
!=
NULL
)
*
value
++
=
0
;
if
(
!
strcmp
(
this_char
,
"check"
))
*
mount_options
|=
EXT2_MOUNT_CHECK
;
else
if
(
!
strcmp
(
this_char
,
"sb"
))
{
if
(
!
strcmp
(
this_char
,
"check"
))
{
if
(
!
value
||
!*
value
)
set_opt
(
*
mount_options
,
CHECK_NORMAL
);
else
if
(
!
strcmp
(
value
,
"none"
))
{
clear_opt
(
*
mount_options
,
CHECK_NORMAL
);
clear_opt
(
*
mount_options
,
CHECK_STRICT
);
}
else
if
(
strcmp
(
value
,
"normal"
))
set_opt
(
*
mount_options
,
CHECK_NORMAL
);
else
if
(
strcmp
(
value
,
"strict"
))
{
set_opt
(
*
mount_options
,
CHECK_NORMAL
);
set_opt
(
*
mount_options
,
CHECK_STRICT
);
}
else
{
printk
(
"EXT2-fs: Invalid check option: %s
\n
"
,
value
);
return
0
;
}
}
else
if
(
!
strcmp
(
this_char
,
"debug"
))
set_opt
(
*
mount_options
,
DEBUG
);
else
if
(
!
strcmp
(
this_char
,
"errors"
))
{
if
(
!
value
||
!*
value
)
{
printk
(
"EXT2-fs: the errors option requires "
"an argument"
);
return
0
;
}
if
(
!
strcmp
(
value
,
"continue"
))
{
clear_opt
(
*
mount_options
,
ERRORS_RO
);
clear_opt
(
*
mount_options
,
ERRORS_PANIC
);
set_opt
(
*
mount_options
,
ERRORS_CONT
);
}
else
if
(
!
strcmp
(
value
,
"remount-ro"
))
{
clear_opt
(
*
mount_options
,
ERRORS_CONT
);
clear_opt
(
*
mount_options
,
ERRORS_PANIC
);
set_opt
(
*
mount_options
,
ERRORS_RO
);
}
else
if
(
!
strcmp
(
value
,
"panic"
))
{
clear_opt
(
*
mount_options
,
ERRORS_CONT
);
clear_opt
(
*
mount_options
,
ERRORS_RO
);
set_opt
(
*
mount_options
,
ERRORS_PANIC
);
}
else
{
printk
(
"EXT2-fs: Invalid errors option: %s
\n
"
,
value
);
return
0
;
}
}
else
if
(
!
strcmp
(
this_char
,
"grpid"
))
set_opt
(
*
mount_options
,
GRPID
);
else
if
(
!
strcmp
(
this_char
,
"nocheck"
))
{
clear_opt
(
*
mount_options
,
CHECK_NORMAL
);
clear_opt
(
*
mount_options
,
CHECK_STRICT
);
}
else
if
(
!
strcmp
(
this_char
,
"nogrpid"
))
clear_opt
(
*
mount_options
,
GRPID
);
else
if
(
!
strcmp
(
this_char
,
"sb"
))
{
if
(
!
value
||
!*
value
)
{
printk
(
"EXT2-fs: the sb option requires "
"an argument"
);
return
0
;
}
*
sb_block
=
simple_strtoul
(
value
,
&
value
,
0
);
if
(
*
value
)
if
(
*
value
)
{
printk
(
"EXT2-fs: Invalid sb option: %s
\n
"
,
value
);
return
0
;
}
}
else
{
printk
(
"EXT2-fs: Unrecognized mount option %s
\n
"
,
this_char
);
return
0
;
...
...
@@ -198,102 +262,191 @@ static int parse_options (char * options, unsigned long * sb_block,
return
1
;
}
struct
super_block
*
ext2_read_super
(
struct
super_block
*
s
,
void
*
data
,
static
void
ext2_setup_super
(
struct
super_block
*
sb
,
struct
ext2_super_block
*
es
)
{
if
(
!
(
sb
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_VALID_FS
))
printk
(
"EXT2-fs warning: mounting unchecked fs, "
"running e2fsck is recommended
\n
"
);
else
if
((
sb
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_ERROR_FS
))
printk
(
"EXT2-fs warning: mounting fs with errors, "
"running e2fsck is recommended
\n
"
);
else
if
(
es
->
s_mnt_count
>=
es
->
s_max_mnt_count
)
printk
(
"EXT2-fs warning: maximal mount count reached, "
"running e2fsck is recommended
\n
"
);
if
(
!
(
sb
->
s_flags
&
MS_RDONLY
))
{
es
->
s_state
&=
~
EXT2_VALID_FS
;
if
(
!
es
->
s_max_mnt_count
)
es
->
s_max_mnt_count
=
EXT2_DFL_MAX_MNT_COUNT
;
es
->
s_mnt_count
++
;
es
->
s_mtime
=
CURRENT_TIME
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
sb
->
s_dirt
=
1
;
if
(
test_opt
(
sb
,
DEBUG
))
printk
(
"[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
"bpg=%lu, ipg=%lu, mo=%04lx]
\n
"
,
EXT2FS_VERSION
,
EXT2FS_DATE
,
sb
->
s_blocksize
,
sb
->
u
.
ext2_sb
.
s_frag_size
,
sb
->
u
.
ext2_sb
.
s_groups_count
,
EXT2_BLOCKS_PER_GROUP
(
sb
),
EXT2_INODES_PER_GROUP
(
sb
),
sb
->
u
.
ext2_sb
.
s_mount_opt
);
if
(
test_opt
(
sb
,
CHECK
))
{
ext2_check_blocks_bitmap
(
sb
);
ext2_check_inodes_bitmap
(
sb
);
}
}
}
static
int
ext2_check_descriptors
(
struct
super_block
*
sb
)
{
int
i
;
int
desc_block
=
0
;
unsigned
long
block
=
sb
->
u
.
ext2_sb
.
s_es
->
s_first_data_block
;
struct
ext2_group_desc
*
gdp
=
NULL
;
ext2_debug
(
"Checking group descriptors"
);
for
(
i
=
0
;
i
<
sb
->
u
.
ext2_sb
.
s_groups_count
;
i
++
)
{
if
((
i
%
EXT2_DESC_PER_BLOCK
(
sb
))
==
0
)
gdp
=
(
struct
ext2_group_desc
*
)
sb
->
u
.
ext2_sb
.
s_group_desc
[
desc_block
++
]
->
b_data
;
if
(
gdp
->
bg_block_bitmap
<
block
||
gdp
->
bg_block_bitmap
>=
block
+
EXT2_BLOCKS_PER_GROUP
(
sb
))
{
ext2_error
(
sb
,
"ext2_check_desciptors"
,
"Block bitmap for group %d"
" not in group (block %lu)!"
,
i
,
gdp
->
bg_block_bitmap
);
return
0
;
}
if
(
gdp
->
bg_inode_bitmap
<
block
||
gdp
->
bg_inode_bitmap
>=
block
+
EXT2_BLOCKS_PER_GROUP
(
sb
))
{
ext2_error
(
sb
,
"ext2_check_desciptors"
,
"Inode bitmap for group %d"
" not in group (block %lu)!"
,
i
,
gdp
->
bg_inode_bitmap
);
return
0
;
}
if
(
gdp
->
bg_inode_table
<
block
||
gdp
->
bg_inode_table
+
sb
->
u
.
ext2_sb
.
s_itb_per_group
>=
block
+
EXT2_BLOCKS_PER_GROUP
(
sb
))
{
ext2_error
(
sb
,
"ext2_check_desciptors"
,
"Inode table for group %d"
" not in group (block %lu)!"
,
i
,
gdp
->
bg_inode_table
);
return
0
;
}
block
+=
EXT2_BLOCKS_PER_GROUP
(
sb
);
gdp
++
;
}
return
1
;
}
struct
super_block
*
ext2_read_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
struct
buffer_head
*
bh
;
struct
ext2_super_block
*
es
;
unsigned
long
sb_block
=
1
;
unsigned
long
logic_sb_block
=
1
;
int
dev
=
s
->
s_dev
;
int
dev
=
s
b
->
s_dev
;
int
bh_count
;
int
i
,
j
;
#ifdef EXT2FS_PRE_02B_COMPAT
int
fs_converted
=
0
;
#endif
s
->
u
.
ext2_sb
.
s_mount_opt
=
0
;
s
et_opt
(
sb
->
u
.
ext2_sb
.
s_mount_opt
,
CHECK_NORMAL
)
;
if
(
!
parse_options
((
char
*
)
data
,
&
sb_block
,
&
s
->
u
.
ext2_sb
.
s_mount_opt
))
{
s
->
s_dev
=
0
;
&
s
b
->
u
.
ext2_sb
.
s_mount_opt
))
{
s
b
->
s_dev
=
0
;
return
NULL
;
}
lock_super
(
s
);
lock_super
(
s
b
);
set_blocksize
(
dev
,
BLOCK_SIZE
);
if
(
!
(
bh
=
bread
(
dev
,
sb_block
,
BLOCK_SIZE
)))
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
printk
(
"EXT2-fs: unable to read superblock
\n
"
);
return
NULL
;
}
/*
* Note: s_es must be initialized s_es as soon as possible because
* some ext2 macro-instructions depend on its value
*/
es
=
(
struct
ext2_super_block
*
)
bh
->
b_data
;
/* Note: s_es must be initialized s_es as soon as possible because
some ext2 macro-instructions depend on its value */
s
->
u
.
ext2_sb
.
s_es
=
es
;
s
->
s_magic
=
es
->
s_magic
;
if
(
s
->
s_magic
!=
EXT2_SUPER_MAGIC
sb
->
u
.
ext2_sb
.
s_es
=
es
;
sb
->
s_magic
=
es
->
s_magic
;
if
(
sb
->
s_magic
!=
EXT2_SUPER_MAGIC
#ifdef EXT2FS_PRE_02B_COMPAT
&&
s
->
s_magic
!=
EXT2_PRE_02B_MAGIC
&&
s
b
->
s_magic
!=
EXT2_PRE_02B_MAGIC
#endif
)
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
if
(
!
silent
)
printk
(
"VFS: Can't find an ext2 filesystem on dev 0x%04x.
\n
"
,
dev
);
return
NULL
;
}
s
->
s_blocksize
=
EXT2_MIN_BLOCK_SIZE
<<
es
->
s_log_block_size
;
s
->
s_blocksize_bits
=
EXT2_BLOCK_SIZE_BITS
(
s
);
if
(
s
->
s_blocksize
!=
BLOCK_SIZE
&&
(
s
->
s_blocksize
==
1024
||
s
->
s_blocksize
==
2048
||
s
->
s_blocksize
==
4096
))
{
s
b
->
s_blocksize
=
EXT2_MIN_BLOCK_SIZE
<<
es
->
s_log_block_size
;
s
b
->
s_blocksize_bits
=
EXT2_BLOCK_SIZE_BITS
(
sb
);
if
(
s
b
->
s_blocksize
!=
BLOCK_SIZE
&&
(
s
b
->
s_blocksize
==
1024
||
sb
->
s_blocksize
==
2048
||
s
b
->
s_blocksize
==
4096
))
{
unsigned
long
offset
;
brelse
(
bh
);
set_blocksize
(
dev
,
s
->
s_blocksize
);
logic_sb_block
=
sb_block
/
s
->
s_blocksize
;
offset
=
sb_block
%
s
->
s_blocksize
;
bh
=
bread
(
dev
,
logic_sb_block
,
s
->
s_blocksize
);
set_blocksize
(
dev
,
s
b
->
s_blocksize
);
logic_sb_block
=
sb_block
/
s
b
->
s_blocksize
;
offset
=
sb_block
%
s
b
->
s_blocksize
;
bh
=
bread
(
dev
,
logic_sb_block
,
s
b
->
s_blocksize
);
if
(
!
bh
)
return
NULL
;
es
=
(
struct
ext2_super_block
*
)
(((
char
*
)
bh
->
b_data
)
+
offset
);
s
->
u
.
ext2_sb
.
s_es
=
es
;
s
b
->
u
.
ext2_sb
.
s_es
=
es
;
if
(
es
->
s_magic
!=
EXT2_SUPER_MAGIC
)
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
printk
(
"EXT2-fs: Magic mismatch, very weird !
\n
"
);
return
NULL
;
}
}
s
->
u
.
ext2_sb
.
s_frag_size
=
EXT2_MIN_FRAG_SIZE
<<
s
b
->
u
.
ext2_sb
.
s_frag_size
=
EXT2_MIN_FRAG_SIZE
<<
es
->
s_log_frag_size
;
if
(
s
->
u
.
ext2_sb
.
s_frag_size
)
s
->
u
.
ext2_sb
.
s_frags_per_block
=
s
->
s_blocksize
/
s
->
u
.
ext2_sb
.
s_frag_size
;
if
(
s
b
->
u
.
ext2_sb
.
s_frag_size
)
s
b
->
u
.
ext2_sb
.
s_frags_per_block
=
sb
->
s_blocksize
/
sb
->
u
.
ext2_sb
.
s_frag_size
;
else
s
->
s_magic
=
0
;
s
->
u
.
ext2_sb
.
s_blocks_per_group
=
es
->
s_blocks_per_group
;
s
->
u
.
ext2_sb
.
s_frags_per_group
=
es
->
s_frags_per_group
;
s
->
u
.
ext2_sb
.
s_inodes_per_group
=
es
->
s_inodes_per_group
;
s
->
u
.
ext2_sb
.
s_inodes_per_block
=
s
->
s_blocksize
/
s
b
->
s_magic
=
0
;
s
b
->
u
.
ext2_sb
.
s_blocks_per_group
=
es
->
s_blocks_per_group
;
s
b
->
u
.
ext2_sb
.
s_frags_per_group
=
es
->
s_frags_per_group
;
s
b
->
u
.
ext2_sb
.
s_inodes_per_group
=
es
->
s_inodes_per_group
;
s
b
->
u
.
ext2_sb
.
s_inodes_per_block
=
sb
->
s_blocksize
/
sizeof
(
struct
ext2_inode
);
s
->
u
.
ext2_sb
.
s_desc_per_block
=
s
->
s_blocksize
/
sb
->
u
.
ext2_sb
.
s_itb_per_group
=
sb
->
u
.
ext2_sb
.
s_inodes_per_group
/
sb
->
u
.
ext2_sb
.
s_inodes_per_block
;
sb
->
u
.
ext2_sb
.
s_desc_per_block
=
sb
->
s_blocksize
/
sizeof
(
struct
ext2_group_desc
);
s
->
u
.
ext2_sb
.
s_sbh
=
bh
;
s
->
u
.
ext2_sb
.
s_es
=
es
;
s
->
u
.
ext2_sb
.
s_mount_state
=
es
->
s_state
;
s
->
u
.
ext2_sb
.
s_rename_lock
=
0
;
s
->
u
.
ext2_sb
.
s_rename_wait
=
NULL
;
s
b
->
u
.
ext2_sb
.
s_sbh
=
bh
;
s
b
->
u
.
ext2_sb
.
s_es
=
es
;
s
b
->
u
.
ext2_sb
.
s_mount_state
=
es
->
s_state
;
s
b
->
u
.
ext2_sb
.
s_rename_lock
=
0
;
s
b
->
u
.
ext2_sb
.
s_rename_wait
=
NULL
;
#ifdef EXT2FS_PRE_02B_COMPAT
if
(
s
->
s_magic
==
EXT2_PRE_02B_MAGIC
)
{
if
(
s
b
->
s_magic
==
EXT2_PRE_02B_MAGIC
)
{
if
(
es
->
s_blocks_count
>
262144
)
{
/* fs > 256 MB can't be converted */
s
->
s_dev
=
0
;
unlock_super
(
s
);
/*
* fs > 256 MB can't be converted
*/
sb
->
s_dev
=
0
;
unlock_super
(
sb
);
brelse
(
bh
);
printk
(
"EXT2-fs: trying to mount a pre-0.2b file"
"system which cannot be converted
\n
"
);
...
...
@@ -301,16 +454,16 @@ struct super_block * ext2_read_super (struct super_block * s, void * data,
}
printk
(
"EXT2-fs: mounting a pre 0.2b file system, "
"will try to convert the structure
\n
"
);
if
(
!
(
s
->
s_flags
&
MS_RDONLY
))
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
if
(
!
(
s
b
->
s_flags
&
MS_RDONLY
))
{
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
printk
(
"EXT2-fs: cannot convert a read-only fs
\n
"
);
return
NULL
;
}
if
(
!
convert_pre_02b_fs
(
s
,
bh
))
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
if
(
!
convert_pre_02b_fs
(
s
b
,
bh
))
{
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
printk
(
"EXT2-fs: conversion failed !!!
\n
"
);
return
NULL
;
...
...
@@ -319,18 +472,18 @@ struct super_block * ext2_read_super (struct super_block * s, void * data,
fs_converted
=
1
;
}
#endif
if
(
s
->
s_magic
!=
EXT2_SUPER_MAGIC
)
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
if
(
s
b
->
s_magic
!=
EXT2_SUPER_MAGIC
)
{
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
if
(
!
silent
)
printk
(
"VFS: Can't find an ext2 filesystem on dev 0x%04x.
\n
"
,
dev
);
return
NULL
;
}
if
(
s
->
s_blocksize
!=
bh
->
b_size
)
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
if
(
s
b
->
s_blocksize
!=
bh
->
b_size
)
{
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
if
(
!
silent
)
printk
(
"VFS: Unsupported blocksize on dev 0x%04x.
\n
"
,
...
...
@@ -338,98 +491,84 @@ struct super_block * ext2_read_super (struct super_block * s, void * data,
return
NULL
;
}
if
(
s
->
s_blocksize
!=
s
->
u
.
ext2_sb
.
s_frag_size
)
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
if
(
s
b
->
s_blocksize
!=
sb
->
u
.
ext2_sb
.
s_frag_size
)
{
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
printk
(
"EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)
\n
"
,
s
->
u
.
ext2_sb
.
s_frag_size
,
s
->
s_blocksize
);
s
b
->
u
.
ext2_sb
.
s_frag_size
,
sb
->
s_blocksize
);
return
NULL
;
}
s
->
u
.
ext2_sb
.
s_groups_count
=
(
es
->
s_blocks_count
-
s
b
->
u
.
ext2_sb
.
s_groups_count
=
(
es
->
s_blocks_count
-
es
->
s_first_data_block
+
EXT2_BLOCKS_PER_GROUP
(
s
)
-
1
)
/
EXT2_BLOCKS_PER_GROUP
(
s
);
EXT2_BLOCKS_PER_GROUP
(
s
b
)
-
1
)
/
EXT2_BLOCKS_PER_GROUP
(
s
b
);
for
(
i
=
0
;
i
<
EXT2_MAX_GROUP_DESC
;
i
++
)
s
->
u
.
ext2_sb
.
s_group_desc
[
i
]
=
NULL
;
bh_count
=
(
s
->
u
.
ext2_sb
.
s_groups_count
+
EXT2_DESC_PER_BLOCK
(
s
)
-
1
)
/
EXT2_DESC_PER_BLOCK
(
s
);
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
]
=
NULL
;
bh_count
=
(
s
b
->
u
.
ext2_sb
.
s_groups_count
+
EXT2_DESC_PER_BLOCK
(
sb
)
-
1
)
/
EXT2_DESC_PER_BLOCK
(
s
b
);
if
(
bh_count
>
EXT2_MAX_GROUP_DESC
)
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
brelse
(
bh
);
printk
(
"EXT2-fs: file system is too big
\n
"
);
return
NULL
;
}
for
(
i
=
0
;
i
<
bh_count
;
i
++
)
{
s
->
u
.
ext2_sb
.
s_group_desc
[
i
]
=
bread
(
dev
,
logic_sb_block
+
i
+
1
,
s
->
s_blocksize
);
if
(
!
s
->
u
.
ext2_sb
.
s_group_desc
[
i
])
{
s
->
s_dev
=
0
;
unlock_super
(
s
);
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
]
=
bread
(
dev
,
logic_sb_block
+
i
+
1
,
sb
->
s_blocksize
);
if
(
!
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
])
{
s
b
->
s_dev
=
0
;
unlock_super
(
s
b
);
for
(
j
=
0
;
j
<
i
;
j
++
)
brelse
(
s
->
u
.
ext2_sb
.
s_group_desc
[
i
]);
brelse
(
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
]);
brelse
(
bh
);
printk
(
"EXT2-fs: unable to read group descriptors
\n
"
);
return
NULL
;
}
}
if
(
!
ext2_check_descriptors
(
sb
))
{
sb
->
s_dev
=
0
;
unlock_super
(
sb
);
for
(
j
=
0
;
j
<
i
;
j
++
)
brelse
(
sb
->
u
.
ext2_sb
.
s_group_desc
[
i
]);
brelse
(
bh
);
printk
(
"EXT2-fs: group descriptors corrupted !
\n
"
);
return
NULL
;
}
for
(
i
=
0
;
i
<
EXT2_MAX_GROUP_LOADED
;
i
++
)
{
s
->
u
.
ext2_sb
.
s_inode_bitmap_number
[
i
]
=
0
;
s
->
u
.
ext2_sb
.
s_inode_bitmap
[
i
]
=
NULL
;
s
->
u
.
ext2_sb
.
s_block_bitmap_number
[
i
]
=
0
;
s
->
u
.
ext2_sb
.
s_block_bitmap
[
i
]
=
NULL
;
}
s
->
u
.
ext2_sb
.
s_loaded_inode_bitmaps
=
0
;
s
->
u
.
ext2_sb
.
s_loaded_block_bitmaps
=
0
;
unlock_super
(
s
);
/* set up enough so that it can read an inode */
s
->
s_dev
=
dev
;
s
->
s_op
=
&
ext2_sops
;
if
(
!
(
s
->
s_mounted
=
iget
(
s
,
EXT2_ROOT_INO
)))
{
s
->
s_dev
=
0
;
sb
->
u
.
ext2_sb
.
s_inode_bitmap_number
[
i
]
=
0
;
sb
->
u
.
ext2_sb
.
s_inode_bitmap
[
i
]
=
NULL
;
sb
->
u
.
ext2_sb
.
s_block_bitmap_number
[
i
]
=
0
;
sb
->
u
.
ext2_sb
.
s_block_bitmap
[
i
]
=
NULL
;
}
sb
->
u
.
ext2_sb
.
s_loaded_inode_bitmaps
=
0
;
sb
->
u
.
ext2_sb
.
s_loaded_block_bitmaps
=
0
;
unlock_super
(
sb
);
/*
* set up enough so that it can read an inode
*/
sb
->
s_dev
=
dev
;
sb
->
s_op
=
&
ext2_sops
;
if
(
!
(
sb
->
s_mounted
=
iget
(
sb
,
EXT2_ROOT_INO
)))
{
sb
->
s_dev
=
0
;
for
(
i
=
0
;
i
<
EXT2_MAX_GROUP_DESC
;
i
++
)
if
(
s
->
u
.
ext2_sb
.
s_group_desc
[
i
])
brelse
(
s
->
u
.
ext2_sb
.
s_group_desc
[
i
]);
if
(
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
])
brelse
(
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
]);
brelse
(
bh
);
printk
(
"EXT2-fs: get root inode failed
\n
"
);
return
NULL
;
}
if
(
!
(
s
->
s_flags
&
MS_RDONLY
))
{
es
->
s_state
&=
~
EXT2_VALID_FS
;
if
(
!
es
->
s_max_mnt_count
)
es
->
s_max_mnt_count
=
EXT2_DFL_MAX_MNT_COUNT
;
es
->
s_mnt_count
++
;
es
->
s_mtime
=
CURRENT_TIME
;
bh
->
b_dirt
=
1
;
s
->
s_dirt
=
1
;
}
#ifdef EXT2FS_PRE_02B_COMPAT
if
(
fs_converted
)
{
for
(
i
=
0
;
i
<
bh_count
;
i
++
)
s
->
u
.
ext2_sb
.
s_group_desc
[
i
]
->
b_dirt
=
1
;
s
->
s_dirt
=
1
;
s
b
->
u
.
ext2_sb
.
s_group_desc
[
i
]
->
b_dirt
=
1
;
s
b
->
s_dirt
=
1
;
}
#endif
if
(
!
(
s
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_VALID_FS
))
printk
(
"EXT2-fs warning: mounting unchecked file system, "
"running e2fsck is recommended
\n
"
);
else
if
(
s
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_ERROR_FS
)
printk
(
"EXT2-fs warning: mounting file system with errors, "
"running e2fsck is recommended
\n
"
);
else
if
(
es
->
s_mnt_count
>=
es
->
s_max_mnt_count
)
printk
(
"EXT2-fs warning: maximal mount count reached, "
"running e2fsck is recommended
\n
"
);
if
(
s
->
u
.
ext2_sb
.
s_mount_opt
&
EXT2_MOUNT_CHECK
)
{
printk
(
"[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, bpg=%lu, ipg=%lu]
\n
"
,
EXT2FS_VERSION
,
EXT2FS_DATE
,
s
->
s_blocksize
,
s
->
u
.
ext2_sb
.
s_frag_size
,
s
->
u
.
ext2_sb
.
s_groups_count
,
EXT2_BLOCKS_PER_GROUP
(
s
),
EXT2_INODES_PER_GROUP
(
s
));
ext2_check_blocks_bitmap
(
s
);
ext2_check_inodes_bitmap
(
s
);
}
return
s
;
ext2_setup_super
(
sb
,
es
);
return
sb
;
}
static
void
ext2_commit_super
(
struct
super_block
*
sb
,
...
...
@@ -469,9 +608,16 @@ void ext2_write_super (struct super_block * sb)
sb
->
s_dirt
=
0
;
}
int
ext2_remount
(
struct
super_block
*
sb
,
int
*
flags
)
int
ext2_remount
(
struct
super_block
*
sb
,
int
*
flags
,
char
*
data
)
{
struct
ext2_super_block
*
es
;
unsigned
long
tmp
;
/*
* Allow the "check" option to be passed as a remount option.
*/
set_opt
(
sb
->
u
.
ext2_sb
.
s_mount_opt
,
CHECK_NORMAL
);
parse_options
(
data
,
&
tmp
,
&
sb
->
u
.
ext2_sb
.
s_mount_opt
);
es
=
sb
->
u
.
ext2_sb
.
s_es
;
if
((
*
flags
&
MS_RDONLY
)
==
(
sb
->
s_flags
&
MS_RDONLY
))
...
...
@@ -480,9 +626,10 @@ int ext2_remount (struct super_block * sb, int * flags)
if
(
es
->
s_state
&
EXT2_VALID_FS
||
!
(
sb
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_VALID_FS
))
return
0
;
/* OK, we are remounting a valid rw partition rdonly, so set
the rdonly flag and then mark the partition as valid
again. */
/*
* OK, we are remounting a valid rw partition rdonly, so set
* the rdonly flag and then mark the partition as valid again.
*/
es
->
s_state
=
sb
->
u
.
ext2_sb
.
s_mount_state
;
es
->
s_mtime
=
CURRENT_TIME
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
...
...
@@ -490,26 +637,14 @@ int ext2_remount (struct super_block * sb, int * flags)
ext2_commit_super
(
sb
,
es
);
}
else
{
/* Mounting a RDONLY partition read-write, so reread and
store the current valid flag. (It may have been changed
by e2fsck since we originally mounted the partition.) */
/*
* Mounting a RDONLY partition read-write, so reread and
* store the current valid flag. (It may have been changed
* by e2fsck since we originally mounted the partition.)
*/
sb
->
u
.
ext2_sb
.
s_mount_state
=
es
->
s_state
;
es
->
s_state
&=
~
EXT2_VALID_FS
;
if
(
!
es
->
s_max_mnt_count
)
es
->
s_max_mnt_count
=
EXT2_DFL_MAX_MNT_COUNT
;
es
->
s_mnt_count
++
;
es
->
s_mtime
=
CURRENT_TIME
;
sb
->
u
.
ext2_sb
.
s_sbh
->
b_dirt
=
1
;
sb
->
s_dirt
=
1
;
if
(
!
(
sb
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_VALID_FS
))
printk
(
"EXT2-fs warning: remounting unchecked fs, "
"running e2fsck is recommended
\n
"
);
else
if
((
sb
->
u
.
ext2_sb
.
s_mount_state
&
EXT2_ERROR_FS
))
printk
(
"EXT2-fs warning: remounting fs with errors, "
"running e2fsck is recommended
\n
"
);
else
if
(
es
->
s_mnt_count
>=
es
->
s_max_mnt_count
)
printk
(
"EXT2-fs warning: maximal mount count reached, "
"running e2fsck is recommended
\n
"
);
sb
->
s_flags
&=
~
MS_RDONLY
;
ext2_setup_super
(
sb
,
es
);
}
return
0
;
}
...
...
fs/ext2/symlink.c
View file @
c6145b38
/*
* linux/fs/ext2/symlink.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
fs/ext2/truncate.c
View file @
c6145b38
/*
* linux/fs/ext2/truncate.c
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -80,7 +82,7 @@ static int trunc_direct (struct inode * inode)
bh
->
b_dirt
=
1
;
}
brelse
(
bh
);
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
}
return
retry
;
}
...
...
@@ -142,7 +144,7 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
bh
->
b_dirt
=
1
;
}
brelse
(
bh
);
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
inode
->
i_blocks
-=
blocks
;
inode
->
i_dirt
=
1
;
}
...
...
@@ -158,7 +160,7 @@ static int trunc_indirect (struct inode * inode, int offset, unsigned long * p)
*
p
=
0
;
inode
->
i_blocks
-=
blocks
;
inode
->
i_dirt
=
1
;
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
}
if
(
IS_SYNC
(
inode
)
&&
ind_bh
->
b_dirt
)
{
ll_rw_block
(
WRITE
,
1
,
&
ind_bh
);
...
...
@@ -218,7 +220,7 @@ static int trunc_dindirect (struct inode * inode, int offset,
*
p
=
0
;
inode
->
i_blocks
-=
blocks
;
inode
->
i_dirt
=
1
;
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
}
if
(
IS_SYNC
(
inode
)
&&
dind_bh
->
b_dirt
)
{
ll_rw_block
(
WRITE
,
1
,
&
dind_bh
);
...
...
@@ -277,7 +279,7 @@ static int trunc_tindirect (struct inode * inode)
*
p
=
0
;
inode
->
i_blocks
-=
blocks
;
inode
->
i_dirt
=
1
;
ext2_free_block
(
inode
->
i_sb
,
tmp
);
ext2_free_block
s
(
inode
->
i_sb
,
tmp
,
1
);
}
if
(
IS_SYNC
(
inode
)
&&
tind_bh
->
b_dirt
)
{
ll_rw_block
(
WRITE
,
1
,
&
tind_bh
);
...
...
@@ -294,6 +296,7 @@ void ext2_truncate (struct inode * inode)
if
(
!
(
S_ISREG
(
inode
->
i_mode
)
||
S_ISDIR
(
inode
->
i_mode
)
||
S_ISLNK
(
inode
->
i_mode
)))
return
;
ext2_discard_prealloc
(
inode
);
while
(
1
)
{
retry
=
trunc_direct
(
inode
);
retry
|=
trunc_indirect
(
inode
,
EXT2_IND_BLOCK
,
...
...
@@ -312,13 +315,3 @@ void ext2_truncate (struct inode * inode)
inode
->
i_mtime
=
inode
->
i_ctime
=
CURRENT_TIME
;
inode
->
i_dirt
=
1
;
}
/*
* Called when a inode is released. Note that this is different
* from ext2_open: open gets called at every open, but release
* gets called only when /all/ the files are closed.
*/
void
ext2_release
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
printk
(
"ext2_release not implemented
\n
"
);
}
fs/super.c
View file @
c6145b38
...
...
@@ -36,7 +36,7 @@ extern int root_mountflags;
struct
super_block
super_blocks
[
NR_SUPER
];
static
int
do_remount_sb
(
struct
super_block
*
sb
,
int
flags
);
static
int
do_remount_sb
(
struct
super_block
*
sb
,
int
flags
,
char
*
data
);
/* this is initialized in init/main.c */
dev_t
ROOT_DEV
=
0
;
...
...
@@ -210,7 +210,7 @@ static int do_umount(dev_t dev)
if
(
!
(
sb
=
get_super
(
dev
)))
return
-
ENOENT
;
if
(
!
(
sb
->
s_flags
&
MS_RDONLY
))
{
retval
=
do_remount_sb
(
sb
,
MS_RDONLY
);
retval
=
do_remount_sb
(
sb
,
MS_RDONLY
,
0
);
if
(
retval
)
return
retval
;
}
...
...
@@ -344,7 +344,7 @@ static int do_mount(dev_t dev, const char * dir, char * type, int flags, void *
* FS-specific mount options can't be altered by remounting.
*/
static
int
do_remount_sb
(
struct
super_block
*
sb
,
int
flags
)
static
int
do_remount_sb
(
struct
super_block
*
sb
,
int
flags
,
char
*
data
)
{
int
retval
;
...
...
@@ -353,7 +353,7 @@ static int do_remount_sb(struct super_block *sb, int flags)
if
(
!
fs_may_remount_ro
(
sb
->
s_dev
))
return
-
EBUSY
;
if
(
sb
->
s_op
&&
sb
->
s_op
->
remount_fs
)
{
retval
=
sb
->
s_op
->
remount_fs
(
sb
,
&
flags
);
retval
=
sb
->
s_op
->
remount_fs
(
sb
,
&
flags
,
data
);
if
(
retval
)
return
retval
;
}
...
...
@@ -362,7 +362,7 @@ static int do_remount_sb(struct super_block *sb, int flags)
return
0
;
}
static
int
do_remount
(
const
char
*
dir
,
int
flags
)
static
int
do_remount
(
const
char
*
dir
,
int
flags
,
char
*
data
)
{
struct
inode
*
dir_i
;
int
retval
;
...
...
@@ -374,23 +374,54 @@ static int do_remount(const char *dir,int flags)
iput
(
dir_i
);
return
-
EINVAL
;
}
retval
=
do_remount_sb
(
dir_i
->
i_sb
,
flags
);
retval
=
do_remount_sb
(
dir_i
->
i_sb
,
flags
,
data
);
iput
(
dir_i
);
return
retval
;
}
static
int
copy_mount_options
(
char
*
data
,
unsigned
long
*
where
)
{
int
i
;
unsigned
long
page
;
struct
vm_area_struct
*
vma
;
*
where
=
0
;
if
(
!
data
)
return
0
;
for
(
vma
=
current
->
mmap
;
;
)
{
if
(
!
vma
||
(
unsigned
long
)
data
<
vma
->
vm_start
)
{
return
-
EFAULT
;
}
if
((
unsigned
long
)
data
<
vma
->
vm_end
)
break
;
vma
=
vma
->
vm_next
;
}
i
=
vma
->
vm_end
-
(
unsigned
long
)
data
;
if
(
PAGE_SIZE
<=
(
unsigned
long
)
i
)
i
=
PAGE_SIZE
-
1
;
if
(
!
(
page
=
__get_free_page
(
GFP_KERNEL
)))
{
return
-
ENOMEM
;
}
memcpy_fromfs
((
void
*
)
page
,
data
,
i
);
*
where
=
page
;
return
0
;
}
/*
* Flags is a 16-bit value that allows up to 16 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
*
* data is a (void *) that can point to any structure up to PAGE_SIZE-1 bytes, which
* can contain arbitrary fs-dependent information (or be NULL).
* data is a (void *) that can point to any structure up to
* PAGE_SIZE-1 bytes, which can contain arbitrary fs-dependent
* information (or be NULL).
*
* NOTE! As old versions of mount() didn't use this setup, the flags has to have
* a special 16-bit magic number in the hight word: 0xC0ED. If this magic word
* isn't present, the flags and data info isn't used, as the syscall assumes we
* are talking to an older version that didn't understand them.
* NOTE! As old versions of mount() didn't use this setup, the flags
* has to have a special 16-bit magic number in the hight word:
* 0xC0ED. If this magic word isn't present, the flags and data info
* isn't used, as the syscall assumes we are talking to an older
* version that didn't understand them.
*/
asmlinkage
int
sys_mount
(
char
*
dev_name
,
char
*
dir_name
,
char
*
type
,
unsigned
long
new_flags
,
void
*
data
)
...
...
@@ -400,27 +431,29 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
struct
file_operations
*
fops
;
dev_t
dev
;
int
retval
;
char
tmp
[
100
],
*
t
;
int
i
;
char
*
t
;
unsigned
long
flags
=
0
;
unsigned
long
page
=
0
;
if
(
!
suser
())
return
-
EPERM
;
if
((
new_flags
&
(
MS_MGC_MSK
|
MS_REMOUNT
))
==
(
MS_MGC_VAL
|
MS_REMOUNT
))
{
return
do_remount
(
dir_name
,
new_flags
&
~
MS_MGC_MSK
&
~
MS_REMOUNT
);
}
if
(
type
)
{
for
(
i
=
0
;
i
<
100
;
i
++
)
{
if
(
TASK_SIZE
<=
(
unsigned
long
)
type
)
return
-
EFAULT
;
if
(
!
(
tmp
[
i
]
=
get_fs_byte
(
type
++
)))
break
;
if
((
new_flags
&
(
MS_MGC_MSK
|
MS_REMOUNT
))
==
(
MS_MGC_VAL
|
MS_REMOUNT
))
{
retval
=
copy_mount_options
(
data
,
&
page
);
if
(
retval
<
0
)
return
retval
;
retval
=
do_remount
(
dir_name
,
new_flags
&
~
MS_MGC_MSK
&
~
MS_REMOUNT
,
(
char
*
)
page
);
free_page
(
page
);
return
retval
;
}
t
=
tmp
;
}
else
t
=
NULL
;
if
(
!
(
fstype
=
get_fs_type
(
t
)))
retval
=
copy_mount_options
(
type
,
&
page
);
if
(
retval
<
0
)
return
retval
;
fstype
=
get_fs_type
((
char
*
)
page
);
free_page
(
page
);
if
(
!
fstype
)
return
-
ENODEV
;
t
=
fstype
->
name
;
if
(
fstype
->
requires_dev
)
{
...
...
@@ -455,26 +488,10 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
}
if
((
new_flags
&
MS_MGC_MSK
)
==
MS_MGC_VAL
)
{
flags
=
new_flags
&
~
MS_MGC_MSK
;
if
(
data
)
{
struct
vm_area_struct
*
vma
;
for
(
vma
=
current
->
mmap
;
;
)
{
if
(
!
vma
||
(
unsigned
long
)
data
<
vma
->
vm_start
)
{
retval
=
copy_mount_options
(
data
,
&
page
);
if
(
retval
<
0
)
{
iput
(
inode
);
return
-
EFAULT
;
}
if
((
unsigned
long
)
data
<
vma
->
vm_end
)
break
;
vma
=
vma
->
vm_next
;
}
i
=
vma
->
vm_end
-
(
unsigned
long
)
data
;
if
(
PAGE_SIZE
<=
(
unsigned
long
)
i
)
i
=
PAGE_SIZE
-
1
;
if
(
!
(
page
=
__get_free_page
(
GFP_KERNEL
)))
{
iput
(
inode
);
return
-
ENOMEM
;
}
memcpy_fromfs
((
void
*
)
page
,
data
,
i
);
return
retval
;
}
}
retval
=
do_mount
(
dev
,
dir_name
,
t
,
flags
,(
void
*
)
page
);
...
...
include/asm/io.h
View file @
c6145b38
...
...
@@ -7,7 +7,7 @@
* to guarantee better timings even on fast machines.
*
* On the other hand, I'd like to be sure of a non-existent port:
* I feel a bit unsafe about using 0x80
.
* I feel a bit unsafe about using 0x80
(should be safe, though)
*
* Linus
*/
...
...
@@ -24,73 +24,41 @@
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
/* This is the more general version of outb.. */
extern
inline
void
__outb
(
unsigned
char
value
,
unsigned
short
port
)
{
__asm__
__volatile__
(
"outb %b0,%w1"
:
/* no outputs */
:
"a"
(
value
),
"d"
(
port
));
}
/* this is used for constant port numbers < 256.. */
extern
inline
void
__outbc
(
unsigned
char
value
,
unsigned
short
port
)
{
__asm__
__volatile__
(
"outb %b0,%1"
:
/* no outputs */
:
"a"
(
value
),
"i"
(
port
));
}
/* general version of inb */
extern
inline
unsigned
int
__inb
(
unsigned
short
port
)
{
unsigned
int
_v
;
__asm__
__volatile__
(
"inb %w1,%b0"
:
"=a"
(
_v
)
:
"d"
(
port
),
"0"
(
0
));
return
_v
;
}
/* inb with constant port nr 0-255 */
extern
inline
unsigned
int
__inbc
(
unsigned
short
port
)
{
unsigned
int
_v
;
__asm__
__volatile__
(
"inb %1,%b0"
:
"=a"
(
_v
)
:
"i"
(
port
),
"0"
(
0
));
return
_v
;
}
extern
inline
void
__outb_p
(
unsigned
char
value
,
unsigned
short
port
)
{
__asm__
__volatile__
(
"outb %b0,%w1"
:
/* no outputs */
:
"a"
(
value
),
"d"
(
port
));
SLOW_DOWN_IO
;
}
extern
inline
void
__outbc_p
(
unsigned
char
value
,
unsigned
short
port
)
{
__asm__
__volatile__
(
"outb %b0,%1"
:
/* no outputs */
:
"a"
(
value
),
"i"
(
port
));
SLOW_DOWN_IO
;
}
extern
inline
unsigned
int
__inb_p
(
unsigned
short
port
)
{
unsigned
int
_v
;
__asm__
__volatile__
(
"inb %w1,%b0"
:
"=a"
(
_v
)
:
"d"
(
port
),
"0"
(
0
));
SLOW_DOWN_IO
;
return
_v
;
}
extern
inline
unsigned
int
__inbc_p
(
unsigned
short
port
)
{
unsigned
int
_v
;
__asm__
__volatile__
(
"inb %1,%b0"
:
"=a"
(
_v
)
:
"i"
(
port
),
"0"
(
0
));
SLOW_DOWN_IO
;
return
_v
;
}
/*
* Talk about misusing macros..
*/
#define __OUT1(s,x) \
extern inline void __out##s(unsigned x value, unsigned short port) {
#define __OUT2(s,s1,s2) \
__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
#define __OUT(s,s1,x) \
__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \
__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "i" (port)); } \
__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "i" (port)); SLOW_DOWN_IO; }
#define __IN1(s) \
extern inline unsigned int __in##s(unsigned short port) { unsigned int _v;
#define __IN2(s,s1,s2) \
__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
#define __IN(s,s1,i...) \
__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
__IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "i" (port) ,##i ); return _v; } \
__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
__IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "i" (port) ,##i ); SLOW_DOWN_IO; return _v; }
__IN
(
b
,
"b"
,
"0"
(
0
))
__IN
(
w
,
"w"
,
"0"
(
0
))
__IN
(
l
,
""
)
__OUT
(
b
,
"b"
,
char
)
__OUT
(
w
,
"w"
,
short
)
__OUT
(
l
,,
int
)
/*
* Note that due to the way __builtin_constant_p() works, you
...
...
@@ -117,4 +85,44 @@ __asm__ __volatile__ ("inb %1,%b0"
__inbc_p(port) : \
__inb_p(port))
#define outw(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outwc((val),(port)) : \
__outw((val),(port)))
#define inw(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inwc(port) : \
__inw(port))
#define outw_p(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outwc_p((val),(port)) : \
__outw_p((val),(port)))
#define inw_p(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inwc_p(port) : \
__inw_p(port))
#define outl(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outlc((val),(port)) : \
__outl((val),(port)))
#define inl(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inlc(port) : \
__inl(port))
#define outl_p(val,port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outlc_p((val),(port)) : \
__outl_p((val),(port)))
#define inl_p(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inlc_p(port) : \
__inl_p(port))
#endif
include/asm/irq.h
View file @
c6145b38
...
...
@@ -35,7 +35,7 @@ extern void enable_irq(unsigned int);
"movl $" STR(USER_DS) ",%edx\n\t" \
"mov %dx,%fs\n\t" \
"movl $0,%edx\n\t" \
"movl %edx,%db7\n"
"movl %edx,%db7\n
\t
"
/*
* SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers,
...
...
include/linux/ext2_fs.h
View file @
c6145b38
/*
* linux/include/linux/ext2_fs.h
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -38,20 +40,20 @@
#undef EXT2FS_PRE_02B_COMPAT
/*
* Define
EXT2FS_PRE_04_COMPAT to convert ext2 fs prior to 0.4
* Define
DONT_USE_DCACHE to inhibit the directory cache
*/
#define
EXT2_PRE_04_COMPAT
#define
DONT_USE_DCACHE
/*
* Define
DONT_USE_DCACHE to inhibit the directory cache
* Define
EXT2_PREALLOCATE to preallocate data blocks for expanding files
*/
#define
DONT_USE_DCACH
E
#define
EXT2_PREALLOCAT
E
/*
* The second extended file system version
*/
#define EXT2FS_DATE "93/1
1/19
"
#define EXT2FS_VERSION "0.4
a
"
#define EXT2FS_DATE "93/1
2/30
"
#define EXT2FS_VERSION "0.4
b
"
/*
* Debug code
...
...
@@ -242,13 +244,33 @@ struct ext2_inode {
/*
* Mount flags
*/
#define EXT2_MOUNT_CHECK 0x0001
/* Do some more checks */
#define EXT2_MOUNT_CHECK_NORMAL 0x0001
/* Do some more checks */
#define EXT2_MOUNT_CHECK_STRICT 0x0002
/* Do again more checks */
#define EXT2_MOUNT_CHECK (EXT2_MOUNT_CHECK_NORMAL | \
EXT2_MOUNT_CHECK_STRICT)
#define EXT2_MOUNT_GRPID 0x0004
/* Create files with directory's group */
#define EXT2_MOUNT_DEBUG 0x0008
/* Some debugging messages */
#define EXT2_MOUNT_ERRORS_CONT 0x0010
/* Continue on errors */
#define EXT2_MOUNT_ERRORS_RO 0x0020
/* Remount fs ro on errors */
#define EXT2_MOUNT_ERRORS_PANIC 0x0040
/* Panic on errors */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
#define test_opt(sb, opt) ((sb)->u.ext2_sb.s_mount_opt & \
EXT2_MOUNT_##opt)
/*
* Maximal mount counts between two filesystem checks
*/
#define EXT2_DFL_MAX_MNT_COUNT 20
/* Allow 20 mounts */
/*
* Behaviour when detecting errors
*/
#define EXT2_ERRORS_CONTINUE 1
/* Continue execution */
#define EXT2_ERRORS_RO 2
/* Remount fs read-only */
#define EXT2_ERRORS_PANIC 3
/* Panic */
#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE
/*
* Structure of the super block
*/
...
...
@@ -270,7 +292,9 @@ struct ext2_super_block {
unsigned
short
s_max_mnt_count
;
/* Maximal mount count */
unsigned
short
s_magic
;
/* Magic signature */
unsigned
short
s_state
;
/* File system state */
unsigned
long
s_reserved
[
241
];
/* Padding to the end of the block */
unsigned
short
s_errors
;
/* Behaviour when detecting errors */
unsigned
short
s_pad
;
unsigned
long
s_reserved
[
240
];
/* Padding to the end of the block */
};
/*
...
...
@@ -300,12 +324,28 @@ struct ext2_dir_entry {
* Function prototypes
*/
/*
* Ok, these declarations are also in <linux/kernel.h> but none of the
* ext2 source programs needs to include it so they are duplicated here.
*/
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
# define NORET_TYPE __volatile__
# define ATTRIB_NORET
/**/
# define NORET_AND
/**/
#else
# define NORET_TYPE
/**/
# define ATTRIB_NORET __attribute__((noreturn))
# define NORET_AND noreturn,
#endif
/* acl.c */
extern
int
ext2_permission
(
struct
inode
*
,
int
);
/* balloc.c */
extern
int
ext2_new_block
(
struct
super_block
*
,
unsigned
long
);
extern
void
ext2_free_block
(
struct
super_block
*
,
unsigned
long
);
extern
int
ext2_new_block
(
struct
super_block
*
,
unsigned
long
,
unsigned
long
*
,
unsigned
long
*
);
extern
void
ext2_free_blocks
(
struct
super_block
*
,
unsigned
long
,
unsigned
long
);
extern
unsigned
long
ext2_count_free_blocks
(
struct
super_block
*
);
extern
void
ext2_check_blocks_bitmap
(
struct
super_block
*
);
...
...
@@ -351,6 +391,7 @@ extern void ext2_read_inode (struct inode *);
extern
void
ext2_write_inode
(
struct
inode
*
);
extern
void
ext2_put_inode
(
struct
inode
*
);
extern
int
ext2_sync_inode
(
struct
inode
*
);
extern
void
ext2_discard_prealloc
(
struct
inode
*
);
/* ioctl.c */
extern
int
ext2_ioctl
(
struct
inode
*
,
struct
file
*
,
unsigned
int
,
...
...
@@ -374,14 +415,14 @@ extern int ext2_rename (struct inode *, const char *, int,
/* super.c */
extern
void
ext2_error
(
struct
super_block
*
,
const
char
*
,
const
char
*
,
...)
__attribute__
((
format
(
printf
,
3
,
4
)));
extern
volatile
void
ext2_panic
(
struct
super_block
*
,
const
char
*
,
extern
NORET_TYPE
void
ext2_panic
(
struct
super_block
*
,
const
char
*
,
const
char
*
,
...)
__attribute__
((
format
(
printf
,
3
,
4
)));
__attribute__
((
NORET_AND
format
(
printf
,
3
,
4
)));
extern
void
ext2_warning
(
struct
super_block
*
,
const
char
*
,
const
char
*
,
...)
__attribute__
((
format
(
printf
,
3
,
4
)));
extern
void
ext2_put_super
(
struct
super_block
*
);
extern
void
ext2_write_super
(
struct
super_block
*
);
extern
int
ext2_remount
(
struct
super_block
*
,
int
*
);
extern
int
ext2_remount
(
struct
super_block
*
,
int
*
,
char
*
);
extern
struct
super_block
*
ext2_read_super
(
struct
super_block
*
,
void
*
,
int
);
extern
void
ext2_statfs
(
struct
super_block
*
,
struct
statfs
*
);
...
...
include/linux/ext2_fs_i.h
View file @
c6145b38
/*
* linux/include/linux/ext2_fs_i.h
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -30,6 +32,8 @@ struct ext2_inode_info {
unsigned
long
i_block_group
;
unsigned
long
i_next_alloc_block
;
unsigned
long
i_next_alloc_goal
;
unsigned
long
i_prealloc_block
;
unsigned
long
i_prealloc_count
;
};
#endif
/* _LINUX_EXT2_FS_I */
include/linux/ext2_fs_sb.h
View file @
c6145b38
/*
* linux/include/linux/ext2_fs_sb.h
*
* Copyright (C) 1992, 1993 Remy Card (card@masi.ibp.fr)
* Copyright (C) 1992, 1993, 1994 Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
...
...
@@ -26,6 +28,7 @@ struct ext2_sb_info {
unsigned
long
s_frags_per_group
;
/* Number of fragments in a group */
unsigned
long
s_blocks_per_group
;
/* Number of blocks in a group */
unsigned
long
s_inodes_per_group
;
/* Number of inodes in a group */
unsigned
long
s_itb_per_group
;
/* Number of inode table blocks per group */
unsigned
long
s_desc_per_block
;
/* Number of group descriptors per block */
unsigned
long
s_groups_count
;
/* Number of groups in the fs */
struct
buffer_head
*
s_sbh
;
/* Buffer containing the super block */
...
...
include/linux/fs.h
View file @
c6145b38
...
...
@@ -300,7 +300,7 @@ struct super_operations {
void
(
*
put_super
)
(
struct
super_block
*
);
void
(
*
write_super
)
(
struct
super_block
*
);
void
(
*
statfs
)
(
struct
super_block
*
,
struct
statfs
*
);
int
(
*
remount_fs
)
(
struct
super_block
*
,
int
*
);
int
(
*
remount_fs
)
(
struct
super_block
*
,
int
*
,
char
*
);
};
struct
file_system_type
{
...
...
include/linux/net.h
View file @
c6145b38
...
...
@@ -49,7 +49,7 @@ typedef enum {
SS_UNCONNECTED
,
/* unconnected to any socket */
SS_CONNECTING
,
/* in process of connecting */
SS_CONNECTED
,
/* connected to socket */
SS_DISCONNECTING
,
/* in process of disconnecting */
SS_DISCONNECTING
/* in process of disconnecting */
}
socket_state
;
#define SO_ACCEPTCON (1<<16)
/* performed a listen */
...
...
include/linux/nfs.h
View file @
c6145b38
...
...
@@ -25,17 +25,17 @@
enum
rpc_auth_flavor
{
RPC_AUTH_NULL
=
0
,
RPC_AUTH_UNIX
=
1
,
RPC_AUTH_SHORT
=
2
,
RPC_AUTH_SHORT
=
2
};
enum
rpc_msg_type
{
RPC_CALL
=
0
,
RPC_REPLY
=
1
,
RPC_REPLY
=
1
};
enum
rpc_reply_stat
{
RPC_MSG_ACCEPTED
=
0
,
RPC_MSG_DENIED
=
1
,
RPC_MSG_DENIED
=
1
};
enum
rpc_accept_stat
{
...
...
@@ -43,12 +43,12 @@ enum rpc_accept_stat {
RPC_PROG_UNAVAIL
=
1
,
RPC_PROG_MISMATCH
=
2
,
RPC_PROC_UNAVAIL
=
3
,
RPC_GARBAGE_ARGS
=
4
,
RPC_GARBAGE_ARGS
=
4
};
enum
rpc_reject_stat
{
RPC_MISMATCH
=
0
,
RPC_AUTH_ERROR
=
1
,
RPC_AUTH_ERROR
=
1
};
enum
rpc_auth_stat
{
...
...
@@ -56,7 +56,7 @@ enum rpc_auth_stat {
RPC_AUTH_REJECTEDCRED
=
2
,
RPC_AUTH_BADVERF
=
3
,
RPC_AUTH_REJECTEDVERF
=
4
,
RPC_AUTH_TOOWEAK
=
5
,
RPC_AUTH_TOOWEAK
=
5
};
#endif
/* __KERNEL__ */
...
...
@@ -80,7 +80,7 @@ enum nfs_stat {
NFSERR_NOTEMPTY
=
66
,
NFSERR_DQUOT
=
69
,
NFSERR_STALE
=
70
,
NFSERR_WFLUSH
=
99
,
NFSERR_WFLUSH
=
99
};
enum
nfs_ftype
{
...
...
@@ -92,7 +92,7 @@ enum nfs_ftype {
NFLNK
=
5
,
NFSOCK
=
6
,
NFBAD
=
7
,
NFFIFO
=
8
,
NFFIFO
=
8
};
#define NFS_PROGRAM 100003
...
...
include/linux/sockios.h
View file @
c6145b38
...
...
@@ -28,7 +28,7 @@ struct ip_config {
unsigned
long
paddr
;
unsigned
long
router
;
unsigned
long
net
;
unsigned
long
up
:
1
,
destroy
:
1
;
unsigned
int
up
:
1
,
destroy
:
1
;
};
#endif
/* FIXME: */
...
...
net/inet/route.c
View file @
c6145b38
...
...
@@ -170,7 +170,6 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
}
else
{
if
(
!
((
dst
^
dev
->
pa_addr
)
&
dev
->
pa_mask
))
{
mask
=
dev
->
pa_mask
;
dst
&=
mask
;
flags
&=
~
RTF_GATEWAY
;
if
(
flags
&
RTF_DYNAMIC
)
{
/*printk("Dynamic route to my own net rejected\n");*/
...
...
@@ -178,6 +177,7 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
}
}
else
mask
=
guess_mask
(
dst
);
dst
&=
mask
;
}
if
(
gw
==
dev
->
pa_addr
)
flags
&=
~
RTF_GATEWAY
;
...
...
tools/version.c
View file @
c6145b38
...
...
@@ -18,5 +18,4 @@ struct new_utsname system_utsname = {
char
*
linux_banner
=
"Linux version "
UTS_RELEASE
" ("
LINUX_COMPILE_BY
"@"
LINUX_COMPILE_HOST
"."
LINUX_COMPILE_DOMAIN
") "
UTS_VERSION
": "
LINUX_COMPILE_TIME
"
\n
"
;
LINUX_COMPILE_HOST
") "
UTS_VERSION
"
\n
"
;
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