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
5c9cdbba
Commit
5c9cdbba
authored
Nov 01, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://bk.arm.linux.org.uk
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
c68a47a0
36615c12
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
323 additions
and
105 deletions
+323
-105
drivers/block/scsi_ioctl.c
drivers/block/scsi_ioctl.c
+2
-0
drivers/ide/ide-cd.c
drivers/ide/ide-cd.c
+12
-1
drivers/ide/ide-cd.h
drivers/ide/ide-cd.h
+0
-4
fs/ext2/ialloc.c
fs/ext2/ialloc.c
+14
-13
fs/ext2/super.c
fs/ext2/super.c
+12
-5
fs/ext3/ialloc.c
fs/ext3/ialloc.c
+259
-77
fs/ext3/super.c
fs/ext3/super.c
+11
-0
include/linux/blkdev.h
include/linux/blkdev.h
+1
-0
include/linux/ext2_fs.h
include/linux/ext2_fs.h
+4
-2
include/linux/ext2_fs_sb.h
include/linux/ext2_fs_sb.h
+1
-1
include/linux/ext3_fs.h
include/linux/ext3_fs.h
+5
-2
include/linux/ext3_fs_sb.h
include/linux/ext3_fs_sb.h
+2
-0
No files found.
drivers/block/scsi_ioctl.c
View file @
5c9cdbba
...
...
@@ -226,6 +226,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
/*
* fill in request structure
*/
rq
->
cmd_len
=
hdr
.
cmd_len
;
copy_from_user
(
rq
->
cmd
,
hdr
.
cmdp
,
hdr
.
cmd_len
);
if
(
sizeof
(
rq
->
cmd
)
!=
hdr
.
cmd_len
)
memset
(
rq
->
cmd
+
hdr
.
cmd_len
,
0
,
sizeof
(
rq
->
cmd
)
-
hdr
.
cmd_len
);
...
...
@@ -348,6 +349,7 @@ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev,
* get command and data to send to device, if any
*/
err
=
-
EFAULT
;
rq
->
cmd_len
=
cmdlen
;
if
(
copy_from_user
(
rq
->
cmd
,
sic
->
data
,
cmdlen
))
goto
error
;
...
...
drivers/ide/ide-cd.c
View file @
5c9cdbba
...
...
@@ -882,6 +882,15 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
struct
request
*
rq
,
ide_handler_t
*
handler
)
{
/*
* FIXME! This should be 'rq->cmd_len' when that is reliable.
*
* This breaks for real 16-byte commands. however, lots of drives
* currently break if we just send 16-bytes for 10/12 byte commands.
*/
#define MAX_CDB_BYTES 12
int
cmd_len
=
MAX_CDB_BYTES
;
struct
cdrom_info
*
info
=
drive
->
driver_data
;
ide_startstop_t
startstop
;
...
...
@@ -906,7 +915,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
ide_set_handler
(
drive
,
handler
,
rq
->
timeout
,
cdrom_timer_expiry
);
/* Send the command to the device. */
HWIF
(
drive
)
->
atapi_output_bytes
(
drive
,
rq
->
cmd
,
sizeof
(
rq
->
cmd
)
);
HWIF
(
drive
)
->
atapi_output_bytes
(
drive
,
rq
->
cmd
,
cmd_len
);
/* Start the DMA if need be */
if
(
info
->
dma
)
...
...
@@ -3004,6 +3013,7 @@ static int ide_cdrom_prep_fs(request_queue_t *q, struct request *rq)
*/
rq
->
cmd
[
7
]
=
(
blocks
>>
8
)
&
0xff
;
rq
->
cmd
[
8
]
=
blocks
&
0xff
;
rq
->
cmd_len
=
10
;
return
BLKPREP_OK
;
}
...
...
@@ -3026,6 +3036,7 @@ static int ide_cdrom_prep_pc(struct request *rq)
c
[
2
]
=
0
;
c
[
1
]
&=
0xe0
;
c
[
0
]
+=
(
READ_10
-
READ_6
);
rq
->
cmd_len
=
10
;
return
BLKPREP_OK
;
}
...
...
drivers/ide/ide-cd.h
View file @
5c9cdbba
...
...
@@ -104,9 +104,6 @@ struct ide_cd_state_flags {
#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct
packet_command
{
};
/* Structure of a MSF cdrom address. */
struct
atapi_msf
{
byte
reserved
;
...
...
@@ -472,7 +469,6 @@ struct cdrom_info {
struct
request_sense
sense_data
;
struct
request
request_sense_request
;
struct
packet_command
request_sense_pc
;
int
dma
;
int
cmd
;
unsigned
long
last_block
;
...
...
fs/ext2/ialloc.c
View file @
5c9cdbba
...
...
@@ -209,9 +209,7 @@ static void ext2_preread_inode(struct inode *inode)
* For other inodes, search forward from the parent directory\'s block
* group to find a free inode.
*/
#if 0
static int find_group_dir(struct super_block *sb, int parent_group)
static
int
find_group_dir
(
struct
super_block
*
sb
,
struct
inode
*
parent
)
{
struct
ext2_super_block
*
es
=
EXT2_SB
(
sb
)
->
s_es
;
int
ngroups
=
EXT2_SB
(
sb
)
->
s_groups_count
;
...
...
@@ -243,7 +241,6 @@ static int find_group_dir(struct super_block *sb, int parent_group)
mark_buffer_dirty
(
best_bh
);
return
best_group
;
}
#endif
/*
* Orlov's allocator for directories.
...
...
@@ -289,7 +286,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
struct
ext2_group_desc
*
desc
;
struct
buffer_head
*
bh
;
if
(
parent
==
sb
->
s_root
->
d_inode
)
{
if
((
parent
==
sb
->
s_root
->
d_inode
)
||
(
parent
->
i_flags
&
EXT2_TOPDIR_FL
))
{
struct
ext2_group_desc
*
best_desc
=
NULL
;
struct
buffer_head
*
best_bh
=
NULL
;
int
best_ndir
=
inodes_per_group
;
...
...
@@ -342,7 +340,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
desc
=
ext2_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
!
desc
||
!
desc
->
bg_free_inodes_count
)
continue
;
if
(
sbi
->
debts
[
group
]
>=
max_debt
)
if
(
sbi
->
s_
debts
[
group
]
>=
max_debt
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_used_dirs_count
)
>=
max_dirs
)
continue
;
...
...
@@ -447,9 +445,12 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
lock_super
(
sb
);
es
=
EXT2_SB
(
sb
)
->
s_es
;
repeat:
if
(
S_ISDIR
(
mode
))
group
=
find_group_orlov
(
sb
,
dir
);
if
(
S_ISDIR
(
mode
))
{
if
(
test_opt
(
sb
,
OLDALLOC
))
group
=
find_group_dir
(
sb
,
dir
);
else
group
=
find_group_orlov
(
sb
,
dir
);
}
else
group
=
find_group_other
(
sb
,
dir
);
err
=
-
ENOSPC
;
...
...
@@ -488,11 +489,11 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
cpu_to_le32
(
le32_to_cpu
(
es
->
s_free_inodes_count
)
-
1
);
if
(
S_ISDIR
(
mode
))
{
if
(
EXT2_SB
(
sb
)
->
debts
[
group
]
<
255
)
EXT2_SB
(
sb
)
->
debts
[
group
]
++
;
if
(
EXT2_SB
(
sb
)
->
s_
debts
[
group
]
<
255
)
EXT2_SB
(
sb
)
->
s_
debts
[
group
]
++
;
}
else
{
if
(
EXT2_SB
(
sb
)
->
debts
[
group
])
EXT2_SB
(
sb
)
->
debts
[
group
]
--
;
if
(
EXT2_SB
(
sb
)
->
s_
debts
[
group
])
EXT2_SB
(
sb
)
->
s_
debts
[
group
]
--
;
}
mark_buffer_dirty
(
EXT2_SB
(
sb
)
->
s_sbh
);
...
...
fs/ext2/super.c
View file @
5c9cdbba
...
...
@@ -140,6 +140,7 @@ static void ext2_put_super (struct super_block * sb)
if
(
sbi
->
s_group_desc
[
i
])
brelse
(
sbi
->
s_group_desc
[
i
]);
kfree
(
sbi
->
s_group_desc
);
kfree
(
sbi
->
s_debts
);
brelse
(
sbi
->
s_sbh
);
sb
->
s_fs_info
=
NULL
;
kfree
(
sbi
);
...
...
@@ -385,6 +386,10 @@ static int parse_options (char * options,
return
0
;
sbi
->
s_resuid
=
v
;
}
else
if
(
!
strcmp
(
this_char
,
"oldalloc"
))
set_opt
(
sbi
->
s_mount_opt
,
OLDALLOC
);
else
if
(
!
strcmp
(
this_char
,
"orlov"
))
clear_opt
(
sbi
->
s_mount_opt
,
OLDALLOC
);
/* Silently ignore the quota options */
else
if
(
!
strcmp
(
this_char
,
"grpquota"
)
||
!
strcmp
(
this_char
,
"noquota"
)
...
...
@@ -756,13 +761,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
printk
(
"EXT2-fs: not enough memory
\n
"
);
goto
failed_mount
;
}
sbi
->
debts
=
kmalloc
(
sbi
->
s_groups_count
*
sizeof
(
*
sbi
->
debts
),
sbi
->
s_debts
=
kmalloc
(
sbi
->
s_groups_count
*
sizeof
(
*
sbi
->
s_
debts
),
GFP_KERNEL
);
if
(
!
sbi
->
debts
)
{
if
(
!
sbi
->
s_
debts
)
{
printk
(
"EXT2-fs: not enough memory
\n
"
);
goto
failed_mount_group_desc
;
}
memset
(
sbi
->
debts
,
0
,
sbi
->
s_groups_count
*
sizeof
(
*
sbi
->
debts
));
memset
(
sbi
->
s_debts
,
0
,
sbi
->
s_groups_count
*
sizeof
(
*
sbi
->
s_
debts
));
for
(
i
=
0
;
i
<
db_count
;
i
++
)
{
block
=
descriptor_loc
(
sb
,
logic_sb_block
,
i
);
sbi
->
s_group_desc
[
i
]
=
sb_bread
(
sb
,
block
);
...
...
@@ -771,7 +776,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
brelse
(
sbi
->
s_group_desc
[
j
]);
kfree
(
sbi
->
s_group_desc
);
printk
(
"EXT2-fs: unable to read group descriptors
\n
"
);
goto
failed_mount
;
goto
failed_mount
_group_desc
;
}
}
if
(
!
ext2_check_descriptors
(
sb
))
{
...
...
@@ -808,6 +813,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
brelse
(
sbi
->
s_group_desc
[
i
]);
failed_mount_group_desc:
kfree
(
sbi
->
s_group_desc
);
if
(
sbi
->
s_debts
)
kfree
(
sbi
->
s_debts
);
failed_mount:
brelse
(
bh
);
failed_sbi:
...
...
fs/ext3/ialloc.c
View file @
5c9cdbba
...
...
@@ -21,6 +21,7 @@
#include <linux/string.h>
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
#include <linux/random.h>
#include <asm/bitops.h>
#include <asm/byteorder.h>
...
...
@@ -191,6 +192,230 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
unlock_super
(
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
* free space and a low directory-to-inode ratio; if that fails, then of
* the groups with above-average free space, that group with the fewest
* directories already is chosen.
*
* For other inodes, search forward from the parent directory\'s block
* group to find a free inode.
*/
static
int
find_group_dir
(
struct
super_block
*
sb
,
struct
inode
*
parent
)
{
struct
ext3_super_block
*
es
=
EXT3_SB
(
sb
)
->
s_es
;
int
ngroups
=
EXT3_SB
(
sb
)
->
s_groups_count
;
int
avefreei
=
le32_to_cpu
(
es
->
s_free_inodes_count
)
/
ngroups
;
struct
ext3_group_desc
*
desc
,
*
best_desc
=
NULL
;
struct
buffer_head
*
bh
,
*
best_bh
=
NULL
;
int
group
,
best_group
=
-
1
;
for
(
group
=
0
;
group
<
ngroups
;
group
++
)
{
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
!
desc
||
!
desc
->
bg_free_inodes_count
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_free_inodes_count
)
<
avefreei
)
continue
;
if
(
!
best_desc
||
(
le16_to_cpu
(
desc
->
bg_free_blocks_count
)
>
le16_to_cpu
(
best_desc
->
bg_free_blocks_count
)))
{
best_group
=
group
;
best_desc
=
desc
;
best_bh
=
bh
;
}
}
if
(
!
best_desc
)
return
-
1
;
best_desc
->
bg_free_inodes_count
=
cpu_to_le16
(
le16_to_cpu
(
best_desc
->
bg_free_inodes_count
)
-
1
);
best_desc
->
bg_used_dirs_count
=
cpu_to_le16
(
le16_to_cpu
(
best_desc
->
bg_used_dirs_count
)
+
1
);
mark_buffer_dirty
(
best_bh
);
return
best_group
;
}
/*
* Orlov's allocator for directories.
*
* We always try to spread first-level directories.
*
* If there are blockgroups with both free inodes and free blocks counts
* not worse than average we return one with smallest directory count.
* Otherwise we simply return a random group.
*
* For the rest rules look so:
*
* It's OK to put directory into a group unless
* it has too many directories already (max_dirs) or
* it has too few free inodes left (min_inodes) or
* it has too few free blocks left (min_blocks) or
* it's already running too large debt (max_debt).
* Parent's group is prefered, if it doesn't satisfy these
* conditions we search cyclically through the rest. If none
* of the groups look good we just look for a group with more
* free inodes than average (starting at parent's group).
*
* Debt is incremented each time we allocate a directory and decremented
* when we allocate an inode, within 0--255.
*/
#define INODE_COST 64
#define BLOCK_COST 256
static
int
find_group_orlov
(
struct
super_block
*
sb
,
struct
inode
*
parent
)
{
int
parent_group
=
EXT3_I
(
parent
)
->
i_block_group
;
struct
ext3_sb_info
*
sbi
=
EXT3_SB
(
sb
);
struct
ext3_super_block
*
es
=
sbi
->
s_es
;
int
ngroups
=
sbi
->
s_groups_count
;
int
inodes_per_group
=
EXT3_INODES_PER_GROUP
(
sb
);
int
avefreei
=
le32_to_cpu
(
es
->
s_free_inodes_count
)
/
ngroups
;
int
avefreeb
=
le32_to_cpu
(
es
->
s_free_blocks_count
)
/
ngroups
;
int
blocks_per_dir
;
int
ndirs
=
sbi
->
s_dir_count
;
int
max_debt
,
max_dirs
,
min_blocks
,
min_inodes
;
int
group
=
-
1
,
i
;
struct
ext3_group_desc
*
desc
;
struct
buffer_head
*
bh
;
if
((
parent
==
sb
->
s_root
->
d_inode
)
||
(
parent
->
i_flags
&
EXT3_TOPDIR_FL
))
{
struct
ext3_group_desc
*
best_desc
=
NULL
;
struct
buffer_head
*
best_bh
=
NULL
;
int
best_ndir
=
inodes_per_group
;
int
best_group
=
-
1
;
get_random_bytes
(
&
group
,
sizeof
(
group
));
parent_group
=
(
unsigned
)
group
%
ngroups
;
for
(
i
=
0
;
i
<
ngroups
;
i
++
)
{
group
=
(
parent_group
+
i
)
%
ngroups
;
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
!
desc
||
!
desc
->
bg_free_inodes_count
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_used_dirs_count
)
>=
best_ndir
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_free_inodes_count
)
<
avefreei
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_free_blocks_count
)
<
avefreeb
)
continue
;
best_group
=
group
;
best_ndir
=
le16_to_cpu
(
desc
->
bg_used_dirs_count
);
best_desc
=
desc
;
best_bh
=
bh
;
}
if
(
best_group
>=
0
)
{
desc
=
best_desc
;
bh
=
best_bh
;
group
=
best_group
;
goto
found
;
}
goto
fallback
;
}
blocks_per_dir
=
(
le32_to_cpu
(
es
->
s_blocks_count
)
-
le32_to_cpu
(
es
->
s_free_blocks_count
))
/
ndirs
;
max_dirs
=
ndirs
/
ngroups
+
inodes_per_group
/
16
;
min_inodes
=
avefreei
-
inodes_per_group
/
4
;
min_blocks
=
avefreeb
-
EXT3_BLOCKS_PER_GROUP
(
sb
)
/
4
;
max_debt
=
EXT3_BLOCKS_PER_GROUP
(
sb
)
/
max
(
blocks_per_dir
,
BLOCK_COST
);
if
(
max_debt
*
INODE_COST
>
inodes_per_group
)
max_debt
=
inodes_per_group
/
INODE_COST
;
if
(
max_debt
>
255
)
max_debt
=
255
;
if
(
max_debt
==
0
)
max_debt
=
1
;
for
(
i
=
0
;
i
<
ngroups
;
i
++
)
{
group
=
(
parent_group
+
i
)
%
ngroups
;
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
!
desc
||
!
desc
->
bg_free_inodes_count
)
continue
;
if
(
sbi
->
s_debts
[
group
]
>=
max_debt
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_used_dirs_count
)
>=
max_dirs
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_free_inodes_count
)
<
min_inodes
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_free_blocks_count
)
<
min_blocks
)
continue
;
goto
found
;
}
fallback:
for
(
i
=
0
;
i
<
ngroups
;
i
++
)
{
group
=
(
parent_group
+
i
)
%
ngroups
;
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
!
desc
||
!
desc
->
bg_free_inodes_count
)
continue
;
if
(
le16_to_cpu
(
desc
->
bg_free_inodes_count
)
>=
avefreei
)
goto
found
;
}
return
-
1
;
found:
desc
->
bg_free_inodes_count
=
cpu_to_le16
(
le16_to_cpu
(
desc
->
bg_free_inodes_count
)
-
1
);
desc
->
bg_used_dirs_count
=
cpu_to_le16
(
le16_to_cpu
(
desc
->
bg_used_dirs_count
)
+
1
);
sbi
->
s_dir_count
++
;
mark_buffer_dirty
(
bh
);
return
group
;
}
static
int
find_group_other
(
struct
super_block
*
sb
,
struct
inode
*
parent
)
{
int
parent_group
=
EXT3_I
(
parent
)
->
i_block_group
;
int
ngroups
=
EXT3_SB
(
sb
)
->
s_groups_count
;
struct
ext3_group_desc
*
desc
;
struct
buffer_head
*
bh
;
int
group
,
i
;
/*
* Try to place the inode in its parent directory
*/
group
=
parent_group
;
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
desc
&&
le16_to_cpu
(
desc
->
bg_free_inodes_count
))
goto
found
;
/*
* Use a quadratic hash to find a group with a
* free inode
*/
for
(
i
=
1
;
i
<
ngroups
;
i
<<=
1
)
{
group
+=
i
;
if
(
group
>=
ngroups
)
group
-=
ngroups
;
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
desc
&&
le16_to_cpu
(
desc
->
bg_free_inodes_count
))
goto
found
;
}
/*
* That failed: try linear search for a free inode
*/
group
=
parent_group
+
1
;
for
(
i
=
2
;
i
<
ngroups
;
i
++
)
{
if
(
++
group
>=
ngroups
)
group
=
0
;
desc
=
ext3_get_group_desc
(
sb
,
group
,
&
bh
);
if
(
desc
&&
le16_to_cpu
(
desc
->
bg_free_inodes_count
))
goto
found
;
}
return
-
1
;
found:
desc
->
bg_free_inodes_count
=
cpu_to_le16
(
le16_to_cpu
(
desc
->
bg_free_inodes_count
)
-
1
);
mark_buffer_dirty
(
bh
);
return
group
;
}
/*
* 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
...
...
@@ -206,10 +431,10 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
struct
super_block
*
sb
;
struct
buffer_head
*
bitmap_bh
=
NULL
;
struct
buffer_head
*
bh2
;
int
i
,
j
,
avefreei
;
int
group
;
ino_t
ino
;
struct
inode
*
inode
;
struct
ext3_group_desc
*
gdp
;
struct
ext3_group_desc
*
tmp
;
struct
ext3_super_block
*
es
;
struct
ext3_inode_info
*
ei
;
int
err
=
0
;
...
...
@@ -228,93 +453,35 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
lock_super
(
sb
);
es
=
EXT3_SB
(
sb
)
->
s_es
;
repeat:
gdp
=
NULL
;
i
=
0
;
if
(
S_ISDIR
(
mode
))
{
avefreei
=
le32_to_cpu
(
es
->
s_free_inodes_count
)
/
EXT3_SB
(
sb
)
->
s_groups_count
;
if
(
!
gdp
)
{
for
(
j
=
0
;
j
<
EXT3_SB
(
sb
)
->
s_groups_count
;
j
++
)
{
struct
buffer_head
*
temp_buffer
;
tmp
=
ext3_get_group_desc
(
sb
,
j
,
&
temp_buffer
);
if
(
tmp
&&
le16_to_cpu
(
tmp
->
bg_free_inodes_count
)
&&
le16_to_cpu
(
tmp
->
bg_free_inodes_count
)
>=
avefreei
)
{
if
(
!
gdp
||
(
le16_to_cpu
(
tmp
->
bg_free_blocks_count
)
>
le16_to_cpu
(
gdp
->
bg_free_blocks_count
)))
{
i
=
j
;
gdp
=
tmp
;
bh2
=
temp_buffer
;
}
}
}
}
}
else
{
/*
* Try to place the inode in its parent directory
*/
i
=
EXT3_I
(
dir
)
->
i_block_group
;
tmp
=
ext3_get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
tmp
&&
le16_to_cpu
(
tmp
->
bg_free_inodes_count
))
gdp
=
tmp
;
if
(
test_opt
(
sb
,
OLDALLOC
))
group
=
find_group_dir
(
sb
,
dir
);
else
{
/*
* Use a quadratic hash to find a group with a
* free inode
*/
for
(
j
=
1
;
j
<
EXT3_SB
(
sb
)
->
s_groups_count
;
j
<<=
1
)
{
i
+=
j
;
if
(
i
>=
EXT3_SB
(
sb
)
->
s_groups_count
)
i
-=
EXT3_SB
(
sb
)
->
s_groups_count
;
tmp
=
ext3_get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
tmp
&&
le16_to_cpu
(
tmp
->
bg_free_inodes_count
))
{
gdp
=
tmp
;
break
;
}
}
}
if
(
!
gdp
)
{
/*
* That failed: try linear search for a free inode
*/
i
=
EXT3_I
(
dir
)
->
i_block_group
+
1
;
for
(
j
=
2
;
j
<
EXT3_SB
(
sb
)
->
s_groups_count
;
j
++
)
{
if
(
++
i
>=
EXT3_SB
(
sb
)
->
s_groups_count
)
i
=
0
;
tmp
=
ext3_get_group_desc
(
sb
,
i
,
&
bh2
);
if
(
tmp
&&
le16_to_cpu
(
tmp
->
bg_free_inodes_count
))
{
gdp
=
tmp
;
break
;
}
}
}
}
group
=
find_group_orlov
(
sb
,
dir
);
}
else
group
=
find_group_other
(
sb
,
dir
);
err
=
-
ENOSPC
;
if
(
!
gdp
)
if
(
group
==
-
1
)
goto
out
;
err
=
-
EIO
;
brelse
(
bitmap_bh
);
bitmap_bh
=
read_inode_bitmap
(
sb
,
i
);
bitmap_bh
=
read_inode_bitmap
(
sb
,
group
);
if
(
!
bitmap_bh
)
goto
fail
;
gdp
=
ext3_get_group_desc
(
sb
,
group
,
&
bh2
);
if
((
j
=
ext3_find_first_zero_bit
((
unsigned
long
*
)
bitmap_bh
->
b_data
,
if
((
ino
=
ext3_find_first_zero_bit
((
unsigned
long
*
)
bitmap_bh
->
b_data
,
EXT3_INODES_PER_GROUP
(
sb
)))
<
EXT3_INODES_PER_GROUP
(
sb
))
{
BUFFER_TRACE
(
bitmap_bh
,
"get_write_access"
);
err
=
ext3_journal_get_write_access
(
handle
,
bitmap_bh
);
if
(
err
)
goto
fail
;
if
(
ext3_set_bit
(
j
,
bitmap_bh
->
b_data
))
{
if
(
ext3_set_bit
(
ino
,
bitmap_bh
->
b_data
))
{
ext3_error
(
sb
,
"ext3_new_inode"
,
"bit already set for inode %
d"
,
j
);
"bit already set for inode %
lu"
,
ino
);
goto
repeat
;
}
BUFFER_TRACE
(
bitmap_bh
,
"call ext3_journal_dirty_metadata"
);
...
...
@@ -324,7 +491,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
if
(
le16_to_cpu
(
gdp
->
bg_free_inodes_count
)
!=
0
)
{
ext3_error
(
sb
,
"ext3_new_inode"
,
"Free inodes count corrupted in group %d"
,
i
);
group
);
/* Is it really ENOSPC? */
err
=
-
ENOSPC
;
if
(
sb
->
s_flags
&
MS_RDONLY
)
...
...
@@ -340,11 +507,11 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
}
goto
repeat
;
}
j
+=
i
*
EXT3_INODES_PER_GROUP
(
sb
)
+
1
;
if
(
j
<
EXT3_FIRST_INO
(
sb
)
||
j
>
le32_to_cpu
(
es
->
s_inodes_count
))
{
ino
+=
group
*
EXT3_INODES_PER_GROUP
(
sb
)
+
1
;
if
(
ino
<
EXT3_FIRST_INO
(
sb
)
||
ino
>
le32_to_cpu
(
es
->
s_inodes_count
))
{
ext3_error
(
sb
,
"ext3_new_inode"
,
"reserved inode or inode > inodes count - "
"block_group = %d,
inode=%d"
,
i
,
j
);
"block_group = %d,
inode=%lu"
,
group
,
ino
);
err
=
-
EIO
;
goto
fail
;
}
...
...
@@ -382,7 +549,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
inode
->
i_gid
=
current
->
fsgid
;
inode
->
i_mode
=
mode
;
inode
->
i_ino
=
j
;
inode
->
i_ino
=
ino
;
/* This is the optimal IO size (for stat), not the fs block size */
inode
->
i_blksize
=
PAGE_SIZE
;
inode
->
i_blocks
=
0
;
...
...
@@ -412,7 +579,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
ei
->
i_prealloc_block
=
0
;
ei
->
i_prealloc_count
=
0
;
#endif
ei
->
i_block_group
=
i
;
ei
->
i_block_group
=
group
;
if
(
ei
->
i_flags
&
EXT3_SYNC_FL
)
inode
->
i_flags
|=
S_SYNC
;
...
...
@@ -562,6 +729,21 @@ unsigned long ext3_count_free_inodes (struct super_block * sb)
#endif
}
/* Called at mount-time, super-block is locked */
unsigned
long
ext3_count_dirs
(
struct
super_block
*
sb
)
{
unsigned
long
count
=
0
;
int
i
;
for
(
i
=
0
;
i
<
EXT3_SB
(
sb
)
->
s_groups_count
;
i
++
)
{
struct
ext3_group_desc
*
gdp
=
ext3_get_group_desc
(
sb
,
i
,
NULL
);
if
(
!
gdp
)
continue
;
count
+=
le16_to_cpu
(
gdp
->
bg_used_dirs_count
);
}
return
count
;
}
#ifdef CONFIG_EXT3_CHECK
/* Called at mount-time, super-block is locked */
void
ext3_check_inodes_bitmap
(
struct
super_block
*
sb
)
...
...
fs/ext3/super.c
View file @
5c9cdbba
...
...
@@ -390,6 +390,7 @@ void ext3_put_super (struct super_block * sb)
for
(
i
=
0
;
i
<
sbi
->
s_gdb_count
;
i
++
)
brelse
(
sbi
->
s_group_desc
[
i
]);
kfree
(
sbi
->
s_group_desc
);
kfree
(
sbi
->
s_debts
);
brelse
(
sbi
->
s_sbh
);
/* Debugging code just in case the in-memory inode orphan list
...
...
@@ -1221,6 +1222,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
printk
(
KERN_ERR
"EXT3-fs: not enough memory
\n
"
);
goto
failed_mount
;
}
sbi
->
s_debts
=
kmalloc
(
sbi
->
s_groups_count
*
sizeof
(
*
sbi
->
s_debts
),
GFP_KERNEL
);
if
(
!
sbi
->
s_debts
)
{
printk
(
"EXT3-fs: not enough memory
\n
"
);
goto
failed_mount2
;
}
memset
(
sbi
->
s_debts
,
0
,
sbi
->
s_groups_count
*
sizeof
(
*
sbi
->
s_debts
));
for
(
i
=
0
;
i
<
db_count
;
i
++
)
{
block
=
descriptor_loc
(
sb
,
logic_sb_block
,
i
);
sbi
->
s_group_desc
[
i
]
=
sb_bread
(
sb
,
block
);
...
...
@@ -1236,6 +1244,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
goto
failed_mount2
;
}
sbi
->
s_gdb_count
=
db_count
;
sbi
->
s_dir_count
=
ext3_count_dirs
(
sb
);
/*
* set up enough so that it can read an inode
*/
...
...
@@ -1339,6 +1348,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
failed_mount3:
journal_destroy
(
sbi
->
s_journal
);
failed_mount2:
if
(
sbi
->
s_debts
)
kfree
(
sbi
->
s_debts
);
for
(
i
=
0
;
i
<
db_count
;
i
++
)
brelse
(
sbi
->
s_group_desc
[
i
]);
kfree
(
sbi
->
s_group_desc
);
...
...
include/linux/blkdev.h
View file @
5c9cdbba
...
...
@@ -92,6 +92,7 @@ struct request {
/*
* when request is used as a packet command carrier
*/
unsigned
int
cmd_len
;
unsigned
char
cmd
[
16
];
unsigned
int
data_len
;
...
...
include/linux/ext2_fs.h
View file @
5c9cdbba
...
...
@@ -191,10 +191,11 @@ struct ext2_group_desc
#define EXT2_JOURNAL_DATA_FL 0x00004000
/* Reserved for ext3 */
#define EXT2_NOTAIL_FL 0x00008000
/* file tail should not be merged */
#define EXT2_DIRSYNC_FL 0x00010000
/* dirsync behaviour (directories only) */
#define EXT2_TOPDIR_FL 0x00020000
/* Top of directory hierarchies*/
#define EXT2_RESERVED_FL 0x80000000
/* reserved for ext2 lib */
#define EXT2_FL_USER_VISIBLE 0x000
11
FFF
/* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x000
10
0FF
/* User modifiable flags */
#define EXT2_FL_USER_VISIBLE 0x000
3D
FFF
/* User visible flags */
#define EXT2_FL_USER_MODIFIABLE 0x000
38
0FF
/* User modifiable flags */
/*
* ioctl commands
...
...
@@ -300,6 +301,7 @@ struct ext2_inode {
* Mount flags
*/
#define EXT2_MOUNT_CHECK 0x0001
/* Do mount-time checks */
#define EXT2_MOUNT_OLDALLOC 0x0002
/* Don't use the new Orlov allocator */
#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 */
...
...
include/linux/ext2_fs_sb.h
View file @
5c9cdbba
...
...
@@ -44,7 +44,7 @@ struct ext2_sb_info {
int
s_first_ino
;
u32
s_next_generation
;
unsigned
long
s_dir_count
;
u8
*
debts
;
u8
*
s_
debts
;
};
#endif
/* _LINUX_EXT2_FS_SB */
include/linux/ext3_fs.h
View file @
5c9cdbba
...
...
@@ -186,10 +186,11 @@ struct ext3_group_desc
#define EXT3_JOURNAL_DATA_FL 0x00004000
/* file data should be journaled */
#define EXT3_NOTAIL_FL 0x00008000
/* file tail should not be merged */
#define EXT3_DIRSYNC_FL 0x00010000
/* dirsync behaviour (directories only) */
#define EXT3_TOPDIR_FL 0x00020000
/* Top of directory hierarchies*/
#define EXT3_RESERVED_FL 0x80000000
/* reserved for ext3 lib */
#define EXT3_FL_USER_VISIBLE 0x000
15
FFF
/* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000
10
0FF
/* User modifiable flags */
#define EXT3_FL_USER_VISIBLE 0x000
3D
FFF
/* User visible flags */
#define EXT3_FL_USER_MODIFIABLE 0x000
38
0FF
/* User modifiable flags */
/*
* Inode dynamic state flags
...
...
@@ -308,6 +309,7 @@ struct ext3_inode {
* Mount flags
*/
#define EXT3_MOUNT_CHECK 0x0001
/* Do mount-time checks */
#define EXT3_MOUNT_OLDALLOC 0x0002
/* Don't use the new Orlov allocator */
#define EXT3_MOUNT_GRPID 0x0004
/* Create files with directory's group */
#define EXT3_MOUNT_DEBUG 0x0008
/* Some debugging messages */
#define EXT3_MOUNT_ERRORS_CONT 0x0010
/* Continue on errors */
...
...
@@ -704,6 +706,7 @@ extern struct inode * ext3_new_inode (handle_t *, struct inode *, int);
extern
void
ext3_free_inode
(
handle_t
*
,
struct
inode
*
);
extern
struct
inode
*
ext3_orphan_get
(
struct
super_block
*
,
ino_t
);
extern
unsigned
long
ext3_count_free_inodes
(
struct
super_block
*
);
extern
unsigned
long
ext3_count_dirs
(
struct
super_block
*
);
extern
void
ext3_check_inodes_bitmap
(
struct
super_block
*
);
extern
unsigned
long
ext3_count_free
(
struct
buffer_head
*
,
unsigned
);
...
...
include/linux/ext3_fs_sb.h
View file @
5c9cdbba
...
...
@@ -50,6 +50,8 @@ struct ext3_sb_info {
u32
s_next_generation
;
u32
s_hash_seed
[
4
];
int
s_def_hash_version
;
unsigned
long
s_dir_count
;
u8
*
s_debts
;
/* Journaling */
struct
inode
*
s_journal_inode
;
...
...
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