Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
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