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
99df9271
Commit
99df9271
authored
May 27, 2003
by
Hirofumi Ogawa
Committed by
Arnaldo Carvalho de Melo
May 27, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] Adds the large partition (> 128GB) support to FAT (1/5)
This adds large partition (> 128GB) support to FAT.
parent
38ab2cd5
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
214 additions
and
186 deletions
+214
-186
fs/fat/cache.c
fs/fat/cache.c
+14
-10
fs/fat/dir.c
fs/fat/dir.c
+16
-15
fs/fat/file.c
fs/fat/file.c
+8
-7
fs/fat/inode.c
fs/fat/inode.c
+40
-38
fs/fat/misc.c
fs/fat/misc.c
+69
-54
fs/msdos/namei.c
fs/msdos/namei.c
+36
-33
fs/vfat/namei.c
fs/vfat/namei.c
+17
-16
include/linux/msdos_fs.h
include/linux/msdos_fs.h
+13
-12
include/linux/msdos_fs_i.h
include/linux/msdos_fs_i.h
+1
-1
No files found.
fs/fat/cache.c
View file @
99df9271
...
...
@@ -302,32 +302,36 @@ static int fat_get_cluster(struct inode *inode, int cluster)
return
nr
;
}
int
fat_bmap
(
struct
inode
*
inode
,
int
sector
)
int
fat_bmap
(
struct
inode
*
inode
,
sector_t
sector
,
sector_t
*
phys
)
{
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
sb
);
int
cluster
,
offset
,
last_block
;
sector_t
last_block
;
int
cluster
,
offset
;
*
phys
=
0
;
if
((
sbi
->
fat_bits
!=
32
)
&&
(
inode
->
i_ino
==
MSDOS_ROOT_INO
||
(
S_ISDIR
(
inode
->
i_mode
)
&&
!
MSDOS_I
(
inode
)
->
i_start
)))
{
if
(
sector
>=
sbi
->
dir_entries
>>
sbi
->
dir_per_block_bits
)
return
0
;
return
sector
+
sbi
->
dir_start
;
if
(
sector
<
(
sbi
->
dir_entries
>>
sbi
->
dir_per_block_bits
)
)
*
phys
=
sector
+
sbi
->
dir_start
;
return
0
;
}
last_block
=
(
MSDOS_I
(
inode
)
->
mmu_private
+
(
sb
->
s_blocksize
-
1
))
>>
sb
->
s_blocksize_bits
;
if
(
sector
>=
last_block
)
return
0
;
cluster
=
sector
/
sbi
->
cluster_size
;
offset
=
sector
%
sbi
->
cluster_size
;
cluster
=
sector
>>
(
sbi
->
cluster_bits
-
sb
->
s_blocksize_bits
)
;
offset
=
sector
&
(
sbi
->
cluster_size
-
1
)
;
cluster
=
fat_get_cluster
(
inode
,
cluster
);
if
(
cluster
<
0
)
return
cluster
;
else
if
(
!
cluster
)
return
0
;
return
(
cluster
-
2
)
*
sbi
->
cluster_size
+
sbi
->
data_start
+
offset
;
else
if
(
cluster
)
{
*
phys
=
((
sector_t
)
cluster
-
2
)
*
sbi
->
cluster_size
+
sbi
->
data_start
+
offset
;
}
return
0
;
}
...
...
fs/fat/dir.c
View file @
99df9271
...
...
@@ -191,11 +191,11 @@ int fat_search_long(struct inode *inode, const char *name, int name_len,
int
uni_xlate
=
MSDOS_SB
(
sb
)
->
options
.
unicode_xlate
;
int
utf8
=
MSDOS_SB
(
sb
)
->
options
.
utf8
;
unsigned
short
opt_shortname
=
MSDOS_SB
(
sb
)
->
options
.
shortname
;
int
ino
,
chl
,
i
,
j
,
last_u
,
res
=
0
;
loff_t
cpos
=
0
;
int
chl
,
i
,
j
,
last_u
,
res
=
0
;
loff_t
i_pos
,
cpos
=
0
;
while
(
1
)
{
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
no
)
==
-
1
)
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
_pos
)
==
-
1
)
goto
EODir
;
parse_record:
long_slots
=
0
;
...
...
@@ -246,7 +246,7 @@ int fat_search_long(struct inode *inode, const char *name, int name_len,
if
(
ds
->
id
&
0x40
)
{
unicode
[
offset
+
13
]
=
0
;
}
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
no
)
<
0
)
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
_pos
)
<
0
)
goto
EODir
;
if
(
slot
==
0
)
break
;
...
...
@@ -358,8 +358,9 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
int
utf8
=
MSDOS_SB
(
sb
)
->
options
.
utf8
;
int
nocase
=
MSDOS_SB
(
sb
)
->
options
.
nocase
;
unsigned
short
opt_shortname
=
MSDOS_SB
(
sb
)
->
options
.
shortname
;
int
ino
,
inum
,
chi
,
chl
,
i
,
i2
,
j
,
last
,
last_u
,
dotoffset
=
0
;
loff_t
cpos
;
unsigned
long
inum
;
int
chi
,
chl
,
i
,
i2
,
j
,
last
,
last_u
,
dotoffset
=
0
;
loff_t
i_pos
,
cpos
;
int
ret
=
0
;
lock_kernel
();
...
...
@@ -387,7 +388,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
bh
=
NULL
;
GetNew:
long_slots
=
0
;
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
no
)
==
-
1
)
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
_pos
)
==
-
1
)
goto
EODir
;
/* Check for long filename entry */
if
(
isvfat
)
{
...
...
@@ -445,7 +446,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
if
(
ds
->
id
&
0x40
)
{
unicode
[
offset
+
13
]
=
0
;
}
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
no
)
==
-
1
)
if
(
fat_get_entry
(
inode
,
&
cpos
,
&
bh
,
&
de
,
&
i
_pos
)
==
-
1
)
goto
EODir
;
if
(
slot
==
0
)
break
;
...
...
@@ -533,7 +534,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
else
if
(
!
memcmp
(
de
->
name
,
MSDOS_DOTDOT
,
11
))
{
inum
=
parent_ino
(
filp
->
f_dentry
);
}
else
{
struct
inode
*
tmp
=
fat_iget
(
sb
,
i
no
);
struct
inode
*
tmp
=
fat_iget
(
sb
,
i
_pos
);
if
(
tmp
)
{
inum
=
tmp
->
i_ino
;
iput
(
tmp
);
...
...
@@ -677,14 +678,14 @@ int fat_dir_ioctl(struct inode * inode, struct file * filp,
/***** See if directory is empty */
int
fat_dir_empty
(
struct
inode
*
dir
)
{
loff_t
pos
;
loff_t
pos
,
i_pos
;
struct
buffer_head
*
bh
;
struct
msdos_dir_entry
*
de
;
int
ino
,
result
=
0
;
int
result
=
0
;
pos
=
0
;
bh
=
NULL
;
while
(
fat_get_entry
(
dir
,
&
pos
,
&
bh
,
&
de
,
&
i
no
)
>
-
1
)
{
while
(
fat_get_entry
(
dir
,
&
pos
,
&
bh
,
&
de
,
&
i
_pos
)
>
-
1
)
{
/* Ignore vfat longname entries */
if
(
de
->
attr
==
ATTR_EXT
)
continue
;
...
...
@@ -703,7 +704,7 @@ int fat_dir_empty(struct inode *dir)
/* This assumes that size of cluster is above the 32*slots */
int
fat_add_entries
(
struct
inode
*
dir
,
int
slots
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
)
struct
msdos_dir_entry
**
de
,
loff_t
*
i_pos
)
{
struct
super_block
*
sb
=
dir
->
i_sb
;
loff_t
offset
,
curr
;
...
...
@@ -713,7 +714,7 @@ int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
offset
=
curr
=
0
;
*
bh
=
NULL
;
row
=
0
;
while
(
fat_get_entry
(
dir
,
&
curr
,
bh
,
de
,
i
no
)
>
-
1
)
{
while
(
fat_get_entry
(
dir
,
&
curr
,
bh
,
de
,
i
_pos
)
>
-
1
)
{
/* check the maximum size of directory */
if
(
curr
>=
FAT_MAX_DIR_SIZE
)
{
brelse
(
*
bh
);
...
...
@@ -735,7 +736,7 @@ int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
return
PTR_ERR
(
new_bh
);
brelse
(
new_bh
);
do
{
fat_get_entry
(
dir
,
&
curr
,
bh
,
de
,
i
no
);
fat_get_entry
(
dir
,
&
curr
,
bh
,
de
,
i
_pos
);
}
while
(
++
row
<
slots
);
return
offset
;
...
...
fs/fat/file.c
View file @
99df9271
...
...
@@ -32,11 +32,12 @@ int fat_get_block(struct inode *inode, sector_t iblock,
struct
buffer_head
*
bh_result
,
int
create
)
{
struct
super_block
*
sb
=
inode
->
i_sb
;
unsigned
long
phys
;
sector_t
phys
;
int
err
;
phys
=
fat_bmap
(
inode
,
iblock
);
if
(
phys
<
0
)
return
phys
;
err
=
fat_bmap
(
inode
,
iblock
,
&
phys
);
if
(
err
)
return
err
;
if
(
phys
)
{
map_bh
(
bh_result
,
sb
,
phys
);
return
0
;
...
...
@@ -55,9 +56,9 @@ int fat_get_block(struct inode *inode, sector_t iblock,
return
error
;
}
MSDOS_I
(
inode
)
->
mmu_private
+=
sb
->
s_blocksize
;
phys
=
fat_bmap
(
inode
,
iblock
);
if
(
phys
<
0
)
return
phys
;
err
=
fat_bmap
(
inode
,
iblock
,
&
phys
);
if
(
err
)
return
err
;
if
(
!
phys
)
BUG
();
set_buffer_new
(
bh_result
);
...
...
fs/fat/inode.c
View file @
99df9271
...
...
@@ -60,17 +60,17 @@ void fat_hash_init(void)
}
}
static
inline
unsigned
long
fat_hash
(
struct
super_block
*
sb
,
in
t
i_pos
)
static
inline
unsigned
long
fat_hash
(
struct
super_block
*
sb
,
loff_
t
i_pos
)
{
unsigned
long
tmp
=
(
unsigned
long
)
i_pos
|
(
unsigned
long
)
sb
;
tmp
=
tmp
+
(
tmp
>>
FAT_HASH_BITS
)
+
(
tmp
>>
FAT_HASH_BITS
*
2
);
return
tmp
&
FAT_HASH_MASK
;
}
void
fat_attach
(
struct
inode
*
inode
,
in
t
i_pos
)
void
fat_attach
(
struct
inode
*
inode
,
loff_
t
i_pos
)
{
spin_lock
(
&
fat_inode_lock
);
MSDOS_I
(
inode
)
->
i_
location
=
i_pos
;
MSDOS_I
(
inode
)
->
i_
pos
=
i_pos
;
list_add
(
&
MSDOS_I
(
inode
)
->
i_fat_hash
,
fat_inode_hashtable
+
fat_hash
(
inode
->
i_sb
,
i_pos
));
spin_unlock
(
&
fat_inode_lock
);
...
...
@@ -79,12 +79,12 @@ void fat_attach(struct inode *inode, int i_pos)
void
fat_detach
(
struct
inode
*
inode
)
{
spin_lock
(
&
fat_inode_lock
);
MSDOS_I
(
inode
)
->
i_
location
=
0
;
MSDOS_I
(
inode
)
->
i_
pos
=
0
;
list_del_init
(
&
MSDOS_I
(
inode
)
->
i_fat_hash
);
spin_unlock
(
&
fat_inode_lock
);
}
struct
inode
*
fat_iget
(
struct
super_block
*
sb
,
in
t
i_pos
)
struct
inode
*
fat_iget
(
struct
super_block
*
sb
,
loff_
t
i_pos
)
{
struct
list_head
*
p
=
fat_inode_hashtable
+
fat_hash
(
sb
,
i_pos
);
struct
list_head
*
walk
;
...
...
@@ -96,7 +96,7 @@ struct inode *fat_iget(struct super_block *sb, int i_pos)
i
=
list_entry
(
walk
,
struct
msdos_inode_info
,
i_fat_hash
);
if
(
i
->
vfs_inode
.
i_sb
!=
sb
)
continue
;
if
(
i
->
i_
location
!=
i_pos
)
if
(
i
->
i_
pos
!=
i_pos
)
continue
;
inode
=
igrab
(
&
i
->
vfs_inode
);
if
(
inode
)
...
...
@@ -109,11 +109,11 @@ struct inode *fat_iget(struct super_block *sb, int i_pos)
static
int
fat_fill_inode
(
struct
inode
*
inode
,
struct
msdos_dir_entry
*
de
);
struct
inode
*
fat_build_inode
(
struct
super_block
*
sb
,
struct
msdos_dir_entry
*
de
,
int
ino
,
int
*
res
)
struct
msdos_dir_entry
*
de
,
loff_t
i_pos
,
int
*
res
)
{
struct
inode
*
inode
;
*
res
=
0
;
inode
=
fat_iget
(
sb
,
i
no
);
inode
=
fat_iget
(
sb
,
i
_pos
);
if
(
inode
)
goto
out
;
inode
=
new_inode
(
sb
);
...
...
@@ -128,7 +128,7 @@ struct inode *fat_build_inode(struct super_block *sb,
inode
=
NULL
;
goto
out
;
}
fat_attach
(
inode
,
i
no
);
fat_attach
(
inode
,
i
_pos
);
insert_inode_hash
(
inode
);
out:
return
inode
;
...
...
@@ -500,7 +500,7 @@ static int fat_read_root(struct inode *inode)
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
sb
);
int
error
;
MSDOS_I
(
inode
)
->
i_
location
=
0
;
MSDOS_I
(
inode
)
->
i_
pos
=
0
;
inode
->
i_uid
=
sbi
->
options
.
fs_uid
;
inode
->
i_gid
=
sbi
->
options
.
fs_gid
;
inode
->
i_version
++
;
...
...
@@ -537,9 +537,10 @@ static int fat_read_root(struct inode *inode)
* 0/ i_ino - for fast, reliable lookup if still in the cache
* 1/ i_generation - to see if i_ino is still valid
* bit 0 == 0 iff directory
* 2/ i_location - if ino has changed, but still in cache
* 3/ i_logstart - to semi-verify inode found at i_location
* 4/ parent->i_logstart - maybe used to hunt for the file on disc
* 2/ i_pos - if ino has changed, but still in cache (hi)
* 3/ i_pos - if ino has changed, but still in cache (low)
* 4/ i_logstart - to semi-verify inode found at i_location
* 5/ parent->i_logstart - maybe used to hunt for the file on disc
*
*/
...
...
@@ -551,7 +552,7 @@ struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
if
(
fhtype
!=
3
)
return
ERR_PTR
(
-
ESTALE
);
if
(
len
<
5
)
if
(
len
<
6
)
return
ERR_PTR
(
-
ESTALE
);
return
sb
->
s_export_op
->
find_exported_dentry
(
sb
,
fh
,
NULL
,
acceptable
,
context
);
...
...
@@ -570,13 +571,15 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
inode
=
NULL
;
}
if
(
!
inode
)
{
/* try 2 - see if i_location is in F-d-c
loff_t
i_pos
=
((
loff_t
)
fh
[
2
]
<<
32
)
|
fh
[
3
];
/* try 2 - see if i_pos is in F-d-c
* require i_logstart to be the same
* Will fail if you truncate and then re-write
*/
inode
=
fat_iget
(
sb
,
fh
[
2
]
);
if
(
inode
&&
MSDOS_I
(
inode
)
->
i_logstart
!=
fh
[
3
])
{
inode
=
fat_iget
(
sb
,
i_pos
);
if
(
inode
&&
MSDOS_I
(
inode
)
->
i_logstart
!=
fh
[
4
])
{
iput
(
inode
);
inode
=
NULL
;
}
...
...
@@ -616,15 +619,16 @@ int fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
int
len
=
*
lenp
;
struct
inode
*
inode
=
de
->
d_inode
;
if
(
len
<
5
)
if
(
len
<
6
)
return
255
;
/* no room */
*
lenp
=
5
;
*
lenp
=
6
;
fh
[
0
]
=
inode
->
i_ino
;
fh
[
1
]
=
inode
->
i_generation
;
fh
[
2
]
=
MSDOS_I
(
inode
)
->
i_location
;
fh
[
3
]
=
MSDOS_I
(
inode
)
->
i_logstart
;
fh
[
2
]
=
(
__u32
)(
MSDOS_I
(
inode
)
->
i_pos
>>
32
);
fh
[
3
]
=
(
__u32
)
MSDOS_I
(
inode
)
->
i_pos
;
fh
[
4
]
=
MSDOS_I
(
inode
)
->
i_logstart
;
spin_lock
(
&
de
->
d_lock
);
fh
[
4
]
=
MSDOS_I
(
de
->
d_parent
->
d_inode
)
->
i_logstart
;
fh
[
5
]
=
MSDOS_I
(
de
->
d_parent
->
d_inode
)
->
i_logstart
;
spin_unlock
(
&
de
->
d_lock
);
return
3
;
}
...
...
@@ -635,15 +639,15 @@ struct dentry *fat_get_parent(struct dentry *child)
struct
msdos_dir_entry
*
de
=
NULL
;
struct
dentry
*
parent
=
NULL
;
int
res
;
int
ino
=
0
;
loff_t
i_pos
=
0
;
struct
inode
*
inode
;
lock_kernel
();
res
=
fat_scan
(
child
->
d_inode
,
MSDOS_DOTDOT
,
&
bh
,
&
de
,
&
i
no
);
res
=
fat_scan
(
child
->
d_inode
,
MSDOS_DOTDOT
,
&
bh
,
&
de
,
&
i
_pos
);
if
(
res
<
0
)
goto
out
;
inode
=
fat_build_inode
(
child
->
d_sb
,
de
,
i
no
,
&
res
);
inode
=
fat_build_inode
(
child
->
d_sb
,
de
,
i
_pos
,
&
res
);
if
(
res
)
goto
out
;
if
(
!
inode
)
...
...
@@ -1098,7 +1102,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
sb
);
int
error
;
MSDOS_I
(
inode
)
->
i_
location
=
0
;
MSDOS_I
(
inode
)
->
i_
pos
=
0
;
inode
->
i_uid
=
sbi
->
options
.
fs_uid
;
inode
->
i_gid
=
sbi
->
options
.
fs_gid
;
inode
->
i_version
++
;
...
...
@@ -1112,10 +1116,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
inode
->
i_fop
=
&
fat_dir_operations
;
MSDOS_I
(
inode
)
->
i_start
=
CF_LE_W
(
de
->
start
);
if
(
sbi
->
fat_bits
==
32
)
{
MSDOS_I
(
inode
)
->
i_start
|=
(
CF_LE_W
(
de
->
starthi
)
<<
16
);
}
if
(
sbi
->
fat_bits
==
32
)
MSDOS_I
(
inode
)
->
i_start
|=
(
CF_LE_W
(
de
->
starthi
)
<<
16
);
MSDOS_I
(
inode
)
->
i_logstart
=
MSDOS_I
(
inode
)
->
i_start
;
error
=
fat_calc_dir_size
(
inode
);
if
(
error
<
0
)
...
...
@@ -1131,10 +1134,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
?
S_IRUGO
|
S_IWUGO
:
S_IRWXUGO
)
&
~
sbi
->
options
.
fs_fmask
)
|
S_IFREG
;
MSDOS_I
(
inode
)
->
i_start
=
CF_LE_W
(
de
->
start
);
if
(
sbi
->
fat_bits
==
32
)
{
MSDOS_I
(
inode
)
->
i_start
|=
(
CF_LE_W
(
de
->
starthi
)
<<
16
);
}
if
(
sbi
->
fat_bits
==
32
)
MSDOS_I
(
inode
)
->
i_start
|=
(
CF_LE_W
(
de
->
starthi
)
<<
16
);
MSDOS_I
(
inode
)
->
i_logstart
=
MSDOS_I
(
inode
)
->
i_start
;
inode
->
i_size
=
CF_LE_L
(
de
->
size
);
inode
->
i_op
=
&
fat_file_inode_operations
;
...
...
@@ -1168,22 +1170,22 @@ void fat_write_inode(struct inode *inode, int wait)
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
buffer_head
*
bh
;
struct
msdos_dir_entry
*
raw_entry
;
unsigned
in
t
i_pos
;
loff_
t
i_pos
;
retry:
i_pos
=
MSDOS_I
(
inode
)
->
i_
location
;
i_pos
=
MSDOS_I
(
inode
)
->
i_
pos
;
if
(
inode
->
i_ino
==
MSDOS_ROOT_INO
||
!
i_pos
)
{
return
;
}
lock_kernel
();
if
(
!
(
bh
=
sb_bread
(
sb
,
i_pos
>>
MSDOS_SB
(
sb
)
->
dir_per_block_bits
)))
{
fat_fs_panic
(
sb
,
"unable to read i-node block (i
no %
lu)"
,
fat_fs_panic
(
sb
,
"unable to read i-node block (i
_pos %l
lu)"
,
i_pos
);
unlock_kernel
();
return
;
}
spin_lock
(
&
fat_inode_lock
);
if
(
i_pos
!=
MSDOS_I
(
inode
)
->
i_
location
)
{
if
(
i_pos
!=
MSDOS_I
(
inode
)
->
i_
pos
)
{
spin_unlock
(
&
fat_inode_lock
);
brelse
(
bh
);
unlock_kernel
();
...
...
fs/fat/misc.c
View file @
99df9271
...
...
@@ -178,9 +178,9 @@ int fat_add_cluster(struct inode *inode)
struct
buffer_head
*
fat_extend_dir
(
struct
inode
*
inode
)
{
struct
super_block
*
sb
=
inode
->
i_sb
;
int
nr
,
sector
,
last_sector
;
struct
buffer_head
*
bh
,
*
res
=
NULL
;
int
cluster_size
=
MSDOS_SB
(
sb
)
->
cluster_size
;
int
nr
,
cluster_size
=
MSDOS_SB
(
sb
)
->
cluster_size
;
sector_t
sector
,
last_sector
;
if
(
MSDOS_SB
(
sb
)
->
fat_bits
!=
32
)
{
if
(
inode
->
i_ino
==
MSDOS_ROOT_INO
)
...
...
@@ -191,7 +191,7 @@ struct buffer_head *fat_extend_dir(struct inode *inode)
if
(
nr
<
0
)
return
ERR_PTR
(
nr
);
sector
=
MSDOS_SB
(
sb
)
->
data_start
+
(
nr
-
2
)
*
cluster_size
;
sector
=
((
sector_t
)
nr
-
2
)
*
cluster_size
+
MSDOS_SB
(
sb
)
->
data_start
;
last_sector
=
sector
+
cluster_size
;
for
(
;
sector
<
last_sector
;
sector
++
)
{
if
((
bh
=
sb_getblk
(
sb
,
sector
)))
{
...
...
@@ -289,11 +289,13 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
*/
int
fat__get_entry
(
struct
inode
*
dir
,
loff_t
*
pos
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
)
struct
msdos_dir_entry
**
de
,
loff_t
*
i_pos
)
{
struct
super_block
*
sb
=
dir
->
i_sb
;
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
sb
);
int
sector
,
offset
,
iblock
;
sector_t
phys
,
iblock
;
loff_t
offset
;
int
err
;
next:
offset
=
*
pos
;
...
...
@@ -302,14 +304,14 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
*
bh
=
NULL
;
iblock
=
*
pos
>>
sb
->
s_blocksize_bits
;
sector
=
fat_bmap
(
dir
,
iblock
);
if
(
sector
<=
0
)
err
=
fat_bmap
(
dir
,
iblock
,
&
phys
);
if
(
err
||
!
phys
)
return
-
1
;
/* beyond EOF or error */
*
bh
=
sb_bread
(
sb
,
sector
);
*
bh
=
sb_bread
(
sb
,
phys
);
if
(
*
bh
==
NULL
)
{
printk
(
KERN_ERR
"FAT: Directory bread(block %
d
) failed
\n
"
,
sector
);
printk
(
KERN_ERR
"FAT: Directory bread(block %
llu
) failed
\n
"
,
phys
);
/* skip this block */
*
pos
=
(
iblock
+
1
)
<<
sb
->
s_blocksize_bits
;
goto
next
;
...
...
@@ -318,7 +320,7 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
offset
&=
sb
->
s_blocksize
-
1
;
*
pos
+=
sizeof
(
struct
msdos_dir_entry
);
*
de
=
(
struct
msdos_dir_entry
*
)((
*
bh
)
->
b_data
+
offset
);
*
i
no
=
(
sector
<<
sbi
->
dir_per_block_bits
)
+
(
offset
>>
MSDOS_DIR_BITS
);
*
i
_pos
=
((
loff_t
)
phys
<<
sbi
->
dir_per_block_bits
)
+
(
offset
>>
MSDOS_DIR_BITS
);
return
0
;
}
...
...
@@ -357,7 +359,7 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
done = !IS_FREE(data[entry].name) \
&& ( \
( \
(
MSDOS_SB(sb)
->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
(
sbi
->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \
) \
| CF_LE_W(data[entry].start) \
) == *number;
...
...
@@ -374,35 +376,38 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
(*number)++; \
}
static
int
raw_scan_sector
(
struct
super_block
*
sb
,
int
sector
,
const
char
*
name
,
int
*
number
,
int
*
ino
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
static
int
raw_scan_sector
(
struct
super_block
*
sb
,
sector_t
sector
,
const
char
*
name
,
int
*
number
,
loff_t
*
i_pos
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
{
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
sb
);
struct
buffer_head
*
bh
;
struct
msdos_dir_entry
*
data
;
int
entry
,
start
,
done
;
if
(
!
(
bh
=
sb_bread
(
sb
,
sector
)))
if
(
!
(
bh
=
sb_bread
(
sb
,
sector
)))
return
-
EIO
;
data
=
(
struct
msdos_dir_entry
*
)
bh
->
b_data
;
for
(
entry
=
0
;
entry
<
MSDOS_SB
(
sb
)
->
dir_per_block
;
entry
++
)
{
for
(
entry
=
0
;
entry
<
sbi
->
dir_per_block
;
entry
++
)
{
/* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */
if
(
name
)
{
RSS_NAME
}
else
{
if
(
!
i
no
)
RSS_COUNT
if
(
!
i
_pos
)
RSS_COUNT
else
{
if
(
number
)
RSS_START
else
RSS_FREE
}
}
if
(
done
)
{
if
(
ino
)
*
ino
=
sector
*
MSDOS_SB
(
sb
)
->
dir_per_block
+
entry
;
if
(
i_pos
)
{
*
i_pos
=
((
loff_t
)
sector
<<
sbi
->
dir_per_block_bits
)
+
entry
;
}
start
=
CF_LE_W
(
data
[
entry
].
start
);
if
(
MSDOS_SB
(
sb
)
->
fat_bits
==
32
)
{
if
(
sbi
->
fat_bits
==
32
)
start
|=
(
CF_LE_W
(
data
[
entry
].
starthi
)
<<
16
);
}
if
(
!
res_bh
)
brelse
(
bh
);
else
{
...
...
@@ -422,16 +427,19 @@ static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
* requested entry is found or the end of the directory is reached.
*/
static
int
raw_scan_root
(
struct
super_block
*
sb
,
const
char
*
name
,
int
*
number
,
int
*
ino
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
static
int
raw_scan_root
(
struct
super_block
*
sb
,
const
char
*
name
,
int
*
number
,
loff_t
*
i_pos
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
{
int
count
,
cluster
;
for
(
count
=
0
;
count
<
MSDOS_SB
(
sb
)
->
dir_entries
/
MSDOS_SB
(
sb
)
->
dir_per_block
;
count
++
)
{
if
((
cluster
=
raw_scan_sector
(
sb
,
MSDOS_SB
(
sb
)
->
dir_start
+
count
,
name
,
number
,
ino
,
res_bh
,
res_de
))
>=
0
)
cluster
=
raw_scan_sector
(
sb
,
MSDOS_SB
(
sb
)
->
dir_start
+
count
,
name
,
number
,
i_pos
,
res_bh
,
res_de
);
if
(
cluster
>=
0
)
return
cluster
;
}
return
-
ENOENT
;
...
...
@@ -443,24 +451,29 @@ static int raw_scan_root(struct super_block *sb,const char *name,int *number,int
* requested entry is found or the end of the directory is reached.
*/
static
int
raw_scan_nonroot
(
struct
super_block
*
sb
,
int
start
,
const
char
*
name
,
int
*
number
,
int
*
ino
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
static
int
raw_scan_nonroot
(
struct
super_block
*
sb
,
int
start
,
const
char
*
name
,
int
*
number
,
loff_t
*
i_pos
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
{
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
sb
);
int
count
,
cluster
;
unsigned
long
dir_size
=
0
;
sector_t
sector
;
#ifdef DEBUG
printk
(
"raw_scan_nonroot: start=%d
\n
"
,
start
);
#endif
do
{
for
(
count
=
0
;
count
<
MSDOS_SB
(
sb
)
->
cluster_size
;
count
++
)
{
if
((
cluster
=
raw_scan_sector
(
sb
,(
start
-
2
)
*
MSDOS_SB
(
sb
)
->
cluster_size
+
MSDOS_SB
(
sb
)
->
data_start
+
count
,
name
,
number
,
ino
,
res_bh
,
res_de
))
>=
0
)
for
(
count
=
0
;
count
<
sbi
->
cluster_size
;
count
++
)
{
sector
=
((
sector_t
)
start
-
2
)
*
sbi
->
cluster_size
+
count
+
sbi
->
data_start
;
cluster
=
raw_scan_sector
(
sb
,
sector
,
name
,
number
,
i_pos
,
res_bh
,
res_de
);
if
(
cluster
>=
0
)
return
cluster
;
}
dir_size
+=
1
<<
MSDOS_SB
(
sb
)
->
cluster_bits
;
dir_size
+=
1
<<
sbi
->
cluster_bits
;
if
(
dir_size
>
FAT_MAX_DIR_SIZE
)
{
fat_fs_panic
(
sb
,
"Directory %d: "
"exceeded the maximum size of directory"
,
...
...
@@ -492,13 +505,13 @@ static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
*/
static
int
raw_scan
(
struct
super_block
*
sb
,
int
start
,
const
char
*
name
,
int
*
number
,
int
*
ino
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
loff_t
*
i_pos
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
)
{
if
(
start
)
return
raw_scan_nonroot
(
sb
,
start
,
name
,
number
,
ino
,
res_bh
,
res_de
);
return
raw_scan_nonroot
(
sb
,
start
,
name
,
NULL
,
i_pos
,
res_bh
,
res_de
);
else
return
raw_scan_root
(
sb
,
name
,
number
,
ino
,
res_bh
,
res_de
);
return
raw_scan_root
(
sb
,
name
,
NULL
,
i_pos
,
res_bh
,
res_de
);
}
/*
...
...
@@ -507,19 +520,21 @@ static int raw_scan(struct super_block *sb, int start, const char *name,
*/
int
fat_subdirs
(
struct
inode
*
dir
)
{
int
count
;
struct
msdos_sb_info
*
sbi
=
MSDOS_SB
(
dir
->
i_sb
);
int
number
;
count
=
0
;
if
((
dir
->
i_ino
==
MSDOS_ROOT_INO
)
&&
(
MSDOS_SB
(
dir
->
i_sb
)
->
fat_bits
!=
32
))
{
(
void
)
raw_scan_root
(
dir
->
i_sb
,
NULL
,
&
count
,
NULL
,
NULL
,
NULL
);
}
else
{
if
((
dir
->
i_ino
!=
MSDOS_ROOT_INO
)
&&
!
MSDOS_I
(
dir
)
->
i_start
)
return
0
;
/* in mkdir */
else
(
void
)
raw_scan_nonroot
(
dir
->
i_sb
,
MSDOS_I
(
dir
)
->
i_start
,
NULL
,
&
count
,
NULL
,
NULL
,
NULL
);
number
=
0
;
if
((
dir
->
i_ino
==
MSDOS_ROOT_INO
)
&&
(
sbi
->
fat_bits
!=
32
))
raw_scan_root
(
dir
->
i_sb
,
NULL
,
&
number
,
NULL
,
NULL
,
NULL
);
else
{
if
((
dir
->
i_ino
!=
MSDOS_ROOT_INO
)
&&
!
MSDOS_I
(
dir
)
->
i_start
)
return
0
;
/* in mkdir */
else
{
raw_scan_nonroot
(
dir
->
i_sb
,
MSDOS_I
(
dir
)
->
i_start
,
NULL
,
&
number
,
NULL
,
NULL
,
NULL
);
}
}
return
count
;
return
number
;
}
...
...
@@ -528,12 +543,12 @@ int fat_subdirs(struct inode *dir)
* for an empty directory slot (name is NULL). Returns an error code or zero.
*/
int
fat_scan
(
struct
inode
*
dir
,
const
char
*
name
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
,
int
*
ino
)
int
fat_scan
(
struct
inode
*
dir
,
const
char
*
name
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
,
loff_t
*
i_pos
)
{
int
res
;
res
=
raw_scan
(
dir
->
i_sb
,
MSDOS_I
(
dir
)
->
i_start
,
name
,
NULL
,
ino
,
res_bh
,
res_de
);
return
res
<
0
?
res
:
0
;
res
=
raw_scan
(
dir
->
i_sb
,
MSDOS_I
(
dir
)
->
i_start
,
name
,
i_pos
,
res_bh
,
res_de
);
return
(
res
<
0
)
?
res
:
0
;
}
fs/msdos/namei.c
View file @
99df9271
...
...
@@ -112,8 +112,9 @@ static int msdos_format_name(const char *name,int len,
}
/***** Locates a directory entry. Uses unformatted name. */
static
int
msdos_find
(
struct
inode
*
dir
,
const
char
*
name
,
int
len
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
)
static
int
msdos_find
(
struct
inode
*
dir
,
const
char
*
name
,
int
len
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
loff_t
*
i_pos
)
{
int
res
;
char
dotsOK
;
...
...
@@ -123,7 +124,7 @@ static int msdos_find(struct inode *dir,const char *name,int len,
res
=
msdos_format_name
(
name
,
len
,
msdos_name
,
&
MSDOS_SB
(
dir
->
i_sb
)
->
options
);
if
(
res
<
0
)
return
-
ENOENT
;
res
=
fat_scan
(
dir
,
msdos_name
,
bh
,
de
,
ino
);
res
=
fat_scan
(
dir
,
msdos_name
,
bh
,
de
,
i_pos
);
if
(
!
res
&&
dotsOK
)
{
if
(
name
[
0
]
==
'.'
)
{
if
(
!
((
*
de
)
->
attr
&
ATTR_HIDDEN
))
...
...
@@ -134,7 +135,6 @@ static int msdos_find(struct inode *dir,const char *name,int len,
}
}
return
res
;
}
/*
...
...
@@ -199,19 +199,19 @@ struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry)
struct
inode
*
inode
=
NULL
;
struct
msdos_dir_entry
*
de
;
struct
buffer_head
*
bh
=
NULL
;
int
ino
,
res
;
loff_t
i_pos
;
int
res
;
dentry
->
d_op
=
&
msdos_dentry_operations
;
lock_kernel
();
res
=
msdos_find
(
dir
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
&
bh
,
&
de
,
&
ino
);
&
de
,
&
i_pos
);
if
(
res
==
-
ENOENT
)
goto
add
;
if
(
res
<
0
)
goto
out
;
inode
=
fat_build_inode
(
sb
,
de
,
i
no
,
&
res
);
inode
=
fat_build_inode
(
sb
,
de
,
i
_pos
,
&
res
);
if
(
res
)
goto
out
;
add:
...
...
@@ -231,12 +231,11 @@ struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry)
static
int
msdos_add_entry
(
struct
inode
*
dir
,
const
char
*
name
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
,
int
is_dir
,
int
is_hid
)
loff_t
*
i_pos
,
int
is_dir
,
int
is_hid
)
{
int
res
;
res
=
fat_add_entries
(
dir
,
1
,
bh
,
de
,
i
no
);
res
=
fat_add_entries
(
dir
,
1
,
bh
,
de
,
i
_pos
);
if
(
res
<
0
)
return
res
;
...
...
@@ -268,7 +267,8 @@ int msdos_create(struct inode *dir,struct dentry *dentry,int mode)
struct
buffer_head
*
bh
;
struct
msdos_dir_entry
*
de
;
struct
inode
*
inode
;
int
ino
,
res
,
is_hid
;
loff_t
i_pos
;
int
res
,
is_hid
;
char
msdos_name
[
MSDOS_NAME
];
lock_kernel
();
...
...
@@ -280,18 +280,18 @@ int msdos_create(struct inode *dir,struct dentry *dentry,int mode)
}
is_hid
=
(
dentry
->
d_name
.
name
[
0
]
==
'.'
)
&&
(
msdos_name
[
0
]
!=
'.'
);
/* Have to do it due to foo vs. .foo conflicts */
if
(
fat_scan
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
ino
)
>=
0
)
{
if
(
fat_scan
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
i_pos
)
>=
0
)
{
brelse
(
bh
);
unlock_kernel
();
return
-
EINVAL
;
}
inode
=
NULL
;
res
=
msdos_add_entry
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
i
no
,
0
,
is_hid
);
res
=
msdos_add_entry
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
i
_pos
,
0
,
is_hid
);
if
(
res
)
{
unlock_kernel
();
return
res
;
}
inode
=
fat_build_inode
(
dir
->
i_sb
,
de
,
i
no
,
&
res
);
inode
=
fat_build_inode
(
dir
->
i_sb
,
de
,
i
_pos
,
&
res
);
brelse
(
bh
);
if
(
!
inode
)
{
unlock_kernel
();
...
...
@@ -308,14 +308,15 @@ int msdos_create(struct inode *dir,struct dentry *dentry,int mode)
int
msdos_rmdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
int
res
,
ino
;
loff_t
i_pos
;
int
res
;
struct
buffer_head
*
bh
;
struct
msdos_dir_entry
*
de
;
bh
=
NULL
;
lock_kernel
();
res
=
msdos_find
(
dir
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
&
bh
,
&
de
,
&
ino
);
&
bh
,
&
de
,
&
i_pos
);
if
(
res
<
0
)
goto
rmdir_done
;
/*
...
...
@@ -351,7 +352,7 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
struct
inode
*
inode
;
int
res
,
is_hid
;
char
msdos_name
[
MSDOS_NAME
];
int
ino
;
loff_t
i_pos
;
lock_kernel
();
res
=
msdos_format_name
(
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
...
...
@@ -362,13 +363,13 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
}
is_hid
=
(
dentry
->
d_name
.
name
[
0
]
==
'.'
)
&&
(
msdos_name
[
0
]
!=
'.'
);
/* foo vs .foo situation */
if
(
fat_scan
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
ino
)
>=
0
)
if
(
fat_scan
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
i_pos
)
>=
0
)
goto
out_exist
;
res
=
msdos_add_entry
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
i
no
,
1
,
is_hid
);
res
=
msdos_add_entry
(
dir
,
msdos_name
,
&
bh
,
&
de
,
&
i
_pos
,
1
,
is_hid
);
if
(
res
)
goto
out_unlock
;
inode
=
fat_build_inode
(
dir
->
i_sb
,
de
,
i
no
,
&
res
);
inode
=
fat_build_inode
(
dir
->
i_sb
,
de
,
i
_pos
,
&
res
);
if
(
!
inode
)
{
brelse
(
bh
);
goto
out_unlock
;
...
...
@@ -414,14 +415,15 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
int
msdos_unlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
int
res
,
ino
;
loff_t
i_pos
;
int
res
;
struct
buffer_head
*
bh
;
struct
msdos_dir_entry
*
de
;
bh
=
NULL
;
lock_kernel
();
res
=
msdos_find
(
dir
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
&
bh
,
&
de
,
&
ino
);
&
bh
,
&
de
,
&
i_pos
);
if
(
res
<
0
)
goto
unlink_done
;
...
...
@@ -443,12 +445,12 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
struct
dentry
*
old_dentry
,
struct
inode
*
new_dir
,
char
*
new_name
,
struct
dentry
*
new_dentry
,
struct
buffer_head
*
old_bh
,
struct
msdos_dir_entry
*
old_de
,
int
old_ino
,
int
is_hid
)
struct
msdos_dir_entry
*
old_de
,
loff_t
old_i_pos
,
int
is_hid
)
{
struct
buffer_head
*
new_bh
=
NULL
,
*
dotdot_bh
=
NULL
;
struct
msdos_dir_entry
*
new_de
,
*
dotdot_de
;
struct
inode
*
old_inode
,
*
new_inode
;
int
new_ino
,
dotdot_ino
;
loff_t
new_i_pos
,
dotdot_i_pos
;
int
error
;
int
is_dir
;
...
...
@@ -456,7 +458,8 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
new_inode
=
new_dentry
->
d_inode
;
is_dir
=
S_ISDIR
(
old_inode
->
i_mode
);
if
(
fat_scan
(
new_dir
,
new_name
,
&
new_bh
,
&
new_de
,
&
new_ino
)
>=
0
&&!
new_inode
)
if
(
fat_scan
(
new_dir
,
new_name
,
&
new_bh
,
&
new_de
,
&
new_i_pos
)
>=
0
&&
!
new_inode
)
goto
degenerate_case
;
if
(
is_dir
)
{
if
(
new_inode
)
{
...
...
@@ -465,7 +468,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
goto
out
;
}
error
=
fat_scan
(
old_inode
,
MSDOS_DOTDOT
,
&
dotdot_bh
,
&
dotdot_de
,
&
dotdot_i
no
);
&
dotdot_de
,
&
dotdot_i
_pos
);
if
(
error
<
0
)
{
printk
(
KERN_WARNING
"MSDOS: %s/%s, get dotdot failed, ret=%d
\n
"
,
...
...
@@ -476,7 +479,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
}
if
(
!
new_bh
)
{
error
=
msdos_add_entry
(
new_dir
,
new_name
,
&
new_bh
,
&
new_de
,
&
new_i
no
,
is_dir
,
is_hid
);
&
new_i
_pos
,
is_dir
,
is_hid
);
if
(
error
)
goto
out
;
}
...
...
@@ -489,7 +492,7 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
old_de
->
name
[
0
]
=
DELETED_FLAG
;
mark_buffer_dirty
(
old_bh
);
fat_detach
(
old_inode
);
fat_attach
(
old_inode
,
new_i
no
);
fat_attach
(
old_inode
,
new_i
_pos
);
if
(
is_hid
)
MSDOS_I
(
old_inode
)
->
i_attrs
|=
ATTR_HIDDEN
;
else
...
...
@@ -544,8 +547,8 @@ int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
{
struct
buffer_head
*
old_bh
;
struct
msdos_dir_entry
*
old_de
;
int
old_ino
,
error
;
int
is_hid
,
old_hid
;
/* if new file and old file are hidden */
loff_t
old_i_pos
;
int
error
,
is_hid
,
old_hid
;
/* if new file and old file are hidden */
char
old_msdos_name
[
MSDOS_NAME
],
new_msdos_name
[
MSDOS_NAME
];
lock_kernel
();
...
...
@@ -562,13 +565,13 @@ int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
is_hid
=
(
new_dentry
->
d_name
.
name
[
0
]
==
'.'
)
&&
(
new_msdos_name
[
0
]
!=
'.'
);
old_hid
=
(
old_dentry
->
d_name
.
name
[
0
]
==
'.'
)
&&
(
old_msdos_name
[
0
]
!=
'.'
);
error
=
fat_scan
(
old_dir
,
old_msdos_name
,
&
old_bh
,
&
old_de
,
&
old_i
no
);
error
=
fat_scan
(
old_dir
,
old_msdos_name
,
&
old_bh
,
&
old_de
,
&
old_i
_pos
);
if
(
error
<
0
)
goto
rename_done
;
error
=
do_msdos_rename
(
old_dir
,
old_msdos_name
,
old_dentry
,
new_dir
,
new_msdos_name
,
new_dentry
,
old_bh
,
old_de
,
(
ino_t
)
old_ino
,
is_hid
);
old_bh
,
old_de
,
old_i_pos
,
is_hid
);
brelse
(
old_bh
);
rename_done:
...
...
fs/vfat/namei.c
View file @
99df9271
...
...
@@ -317,9 +317,10 @@ static int vfat_find_form(struct inode *dir,char *name)
{
struct
msdos_dir_entry
*
de
;
struct
buffer_head
*
bh
=
NULL
;
int
ino
,
res
;
loff_t
i_pos
;
int
res
;
res
=
fat_scan
(
dir
,
name
,
&
bh
,
&
de
,
&
ino
);
res
=
fat_scan
(
dir
,
name
,
&
bh
,
&
de
,
&
i_pos
);
brelse
(
bh
);
if
(
res
<
0
)
return
-
ENOENT
;
...
...
@@ -781,7 +782,7 @@ static int vfat_add_entry(struct inode *dir,struct qstr* qname,
int
res
,
len
;
struct
msdos_dir_entry
*
dummy_de
;
struct
buffer_head
*
dummy_bh
;
int
dummy_ino
;
loff_t
dummy_i_pos
;
dir_slots
=
(
struct
msdos_dir_slot
*
)
kmalloc
(
sizeof
(
struct
msdos_dir_slot
)
*
MSDOS_SLOTS
,
GFP_KERNEL
);
...
...
@@ -797,7 +798,7 @@ static int vfat_add_entry(struct inode *dir,struct qstr* qname,
goto
cleanup
;
/* build the empty directory entry of number of slots */
offset
=
fat_add_entries
(
dir
,
slots
,
&
dummy_bh
,
&
dummy_de
,
&
dummy_i
no
);
offset
=
fat_add_entries
(
dir
,
slots
,
&
dummy_bh
,
&
dummy_de
,
&
dummy_i
_pos
);
if
(
offset
<
0
)
{
res
=
offset
;
goto
cleanup
;
...
...
@@ -807,7 +808,7 @@ static int vfat_add_entry(struct inode *dir,struct qstr* qname,
/* Now create the new entry */
*
bh
=
NULL
;
for
(
slot
=
0
;
slot
<
slots
;
slot
++
)
{
if
(
fat_get_entry
(
dir
,
&
offset
,
bh
,
de
,
&
sinfo_out
->
i
no
)
<
0
)
{
if
(
fat_get_entry
(
dir
,
&
offset
,
bh
,
de
,
&
sinfo_out
->
i
_pos
)
<
0
)
{
res
=
-
EIO
;
goto
cleanup
;
}
...
...
@@ -852,7 +853,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
&
offset
,
&
sinfo
->
longname_offset
);
if
(
res
>
0
)
{
sinfo
->
long_slots
=
res
-
1
;
if
(
fat_get_entry
(
dir
,
&
offset
,
last_bh
,
last_de
,
&
sinfo
->
i
no
)
>=
0
)
if
(
fat_get_entry
(
dir
,
&
offset
,
last_bh
,
last_de
,
&
sinfo
->
i
_pos
)
>=
0
)
return
0
;
res
=
-
EIO
;
}
...
...
@@ -882,7 +883,7 @@ struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
table
++
;
goto
error
;
}
inode
=
fat_build_inode
(
dir
->
i_sb
,
de
,
sinfo
.
i
no
,
&
res
);
inode
=
fat_build_inode
(
dir
->
i_sb
,
de
,
sinfo
.
i
_pos
,
&
res
);
brelse
(
bh
);
if
(
res
)
{
unlock_kernel
();
...
...
@@ -926,7 +927,7 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
unlock_kernel
();
return
res
;
}
inode
=
fat_build_inode
(
sb
,
de
,
sinfo
.
i
no
,
&
res
);
inode
=
fat_build_inode
(
sb
,
de
,
sinfo
.
i
_pos
,
&
res
);
brelse
(
bh
);
if
(
!
inode
)
{
unlock_kernel
();
...
...
@@ -945,8 +946,8 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
static
void
vfat_remove_entry
(
struct
inode
*
dir
,
struct
vfat_slot_info
*
sinfo
,
struct
buffer_head
*
bh
,
struct
msdos_dir_entry
*
de
)
{
loff_t
offset
;
int
i
,
ino
;
loff_t
offset
,
i_pos
;
int
i
;
/* remove the shortname */
dir
->
i_mtime
=
CURRENT_TIME
;
...
...
@@ -958,7 +959,7 @@ static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
/* remove the longname */
offset
=
sinfo
->
longname_offset
;
de
=
NULL
;
for
(
i
=
sinfo
->
long_slots
;
i
>
0
;
--
i
)
{
if
(
fat_get_entry
(
dir
,
&
offset
,
&
bh
,
&
de
,
&
i
no
)
<
0
)
if
(
fat_get_entry
(
dir
,
&
offset
,
&
bh
,
&
de
,
&
i
_pos
)
<
0
)
continue
;
de
->
name
[
0
]
=
DELETED_FLAG
;
de
->
attr
=
ATTR_NONE
;
...
...
@@ -1040,7 +1041,7 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
unlock_kernel
();
return
res
;
}
inode
=
fat_build_inode
(
sb
,
de
,
sinfo
.
i
no
,
&
res
);
inode
=
fat_build_inode
(
sb
,
de
,
sinfo
.
i
_pos
,
&
res
);
if
(
!
inode
)
goto
out
;
inode
->
i_mtime
=
inode
->
i_atime
=
inode
->
i_ctime
=
CURRENT_TIME
;
...
...
@@ -1078,7 +1079,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
{
struct
buffer_head
*
old_bh
,
*
new_bh
,
*
dotdot_bh
;
struct
msdos_dir_entry
*
old_de
,
*
new_de
,
*
dotdot_de
;
int
dotdot_ino
;
loff_t
dotdot_i_pos
;
struct
inode
*
old_inode
,
*
new_inode
;
int
res
,
is_dir
;
struct
vfat_slot_info
old_sinfo
,
sinfo
;
...
...
@@ -1094,13 +1095,13 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
is_dir
=
S_ISDIR
(
old_inode
->
i_mode
);
if
(
is_dir
&&
(
res
=
fat_scan
(
old_inode
,
MSDOS_DOTDOT
,
&
dotdot_bh
,
&
dotdot_de
,
&
dotdot_i
no
))
<
0
)
&
dotdot_de
,
&
dotdot_i
_pos
))
<
0
)
goto
rename_done
;
if
(
new_dentry
->
d_inode
)
{
res
=
vfat_find
(
new_dir
,
&
new_dentry
->
d_name
,
&
sinfo
,
&
new_bh
,
&
new_de
);
if
(
res
<
0
||
MSDOS_I
(
new_inode
)
->
i_
location
!=
sinfo
.
ino
)
{
if
(
res
<
0
||
MSDOS_I
(
new_inode
)
->
i_
pos
!=
sinfo
.
i_pos
)
{
/* WTF??? Cry and fail. */
printk
(
KERN_WARNING
"vfat_rename: fs corrupted
\n
"
);
goto
rename_done
;
...
...
@@ -1124,7 +1125,7 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
vfat_remove_entry
(
old_dir
,
&
old_sinfo
,
old_bh
,
old_de
);
old_bh
=
NULL
;
fat_detach
(
old_inode
);
fat_attach
(
old_inode
,
sinfo
.
i
no
);
fat_attach
(
old_inode
,
sinfo
.
i
_pos
);
mark_inode_dirty
(
old_inode
);
old_dir
->
i_version
++
;
...
...
include/linux/msdos_fs.h
View file @
99df9271
...
...
@@ -178,7 +178,7 @@ struct msdos_dir_slot {
struct
vfat_slot_info
{
int
long_slots
;
/* number of long slots in filename */
loff_t
longname_offset
;
/* dir offset for longname start */
int
ino
;
/* ino for the file
*/
loff_t
i_pos
;
/* on-disk position of directory entry
*/
};
/* Convert attribute bits and a mask to the UNIX mode. */
...
...
@@ -241,7 +241,7 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
/* fat/cache.c */
extern
int
fat_access
(
struct
super_block
*
sb
,
int
nr
,
int
new_value
);
extern
int
__fat_access
(
struct
super_block
*
sb
,
int
nr
,
int
new_value
);
extern
int
fat_bmap
(
struct
inode
*
inode
,
int
sector
);
extern
int
fat_bmap
(
struct
inode
*
inode
,
sector_t
sector
,
sector_t
*
phys
);
extern
void
fat_cache_init
(
void
);
extern
void
fat_cache_lookup
(
struct
inode
*
inode
,
int
cluster
,
int
*
f_clu
,
int
*
d_clu
);
...
...
@@ -259,7 +259,7 @@ extern int fat_dir_ioctl(struct inode * inode, struct file * filp,
unsigned
int
cmd
,
unsigned
long
arg
);
extern
int
fat_dir_empty
(
struct
inode
*
dir
);
extern
int
fat_add_entries
(
struct
inode
*
dir
,
int
slots
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
);
struct
msdos_dir_entry
**
de
,
loff_t
*
i_pos
);
extern
int
fat_new_dir
(
struct
inode
*
dir
,
struct
inode
*
parent
,
int
is_vfat
);
/* fat/file.c */
...
...
@@ -271,11 +271,11 @@ extern void fat_truncate(struct inode *inode);
/* fat/inode.c */
extern
void
fat_hash_init
(
void
);
extern
void
fat_attach
(
struct
inode
*
inode
,
in
t
i_pos
);
extern
void
fat_attach
(
struct
inode
*
inode
,
loff_
t
i_pos
);
extern
void
fat_detach
(
struct
inode
*
inode
);
extern
struct
inode
*
fat_iget
(
struct
super_block
*
sb
,
in
t
i_pos
);
extern
struct
inode
*
fat_iget
(
struct
super_block
*
sb
,
loff_
t
i_pos
);
extern
struct
inode
*
fat_build_inode
(
struct
super_block
*
sb
,
struct
msdos_dir_entry
*
de
,
int
ino
,
int
*
res
);
struct
msdos_dir_entry
*
de
,
loff_t
i_pos
,
int
*
res
);
extern
void
fat_delete_inode
(
struct
inode
*
inode
);
extern
void
fat_clear_inode
(
struct
inode
*
inode
);
extern
void
fat_put_super
(
struct
super_block
*
sb
);
...
...
@@ -295,26 +295,27 @@ extern struct buffer_head *fat_extend_dir(struct inode *inode);
extern
int
date_dos2unix
(
unsigned
short
time
,
unsigned
short
date
);
extern
void
fat_date_unix2dos
(
int
unix_date
,
unsigned
short
*
time
,
unsigned
short
*
date
);
extern
int
fat__get_entry
(
struct
inode
*
dir
,
loff_t
*
pos
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
);
extern
int
fat__get_entry
(
struct
inode
*
dir
,
loff_t
*
pos
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
loff_t
*
i_pos
);
static
__inline__
int
fat_get_entry
(
struct
inode
*
dir
,
loff_t
*
pos
,
struct
buffer_head
**
bh
,
struct
msdos_dir_entry
**
de
,
int
*
ino
)
struct
msdos_dir_entry
**
de
,
loff_t
*
i_pos
)
{
/* Fast stuff first */
if
(
*
bh
&&
*
de
&&
(
*
de
-
(
struct
msdos_dir_entry
*
)(
*
bh
)
->
b_data
)
<
MSDOS_SB
(
dir
->
i_sb
)
->
dir_per_block
-
1
)
{
*
pos
+=
sizeof
(
struct
msdos_dir_entry
);
(
*
de
)
++
;
(
*
i
no
)
++
;
(
*
i
_pos
)
++
;
return
0
;
}
return
fat__get_entry
(
dir
,
pos
,
bh
,
de
,
ino
);
return
fat__get_entry
(
dir
,
pos
,
bh
,
de
,
i_pos
);
}
extern
int
fat_subdirs
(
struct
inode
*
dir
);
extern
int
fat_scan
(
struct
inode
*
dir
,
const
char
*
name
,
struct
buffer_head
**
res_bh
,
struct
msdos_dir_entry
**
res_de
,
int
*
ino
);
struct
msdos_dir_entry
**
res_de
,
loff_t
*
i_pos
);
/* msdos/namei.c - these are for Umsdos */
extern
struct
dentry
*
msdos_lookup
(
struct
inode
*
dir
,
struct
dentry
*
);
...
...
include/linux/msdos_fs_i.h
View file @
99df9271
...
...
@@ -13,7 +13,7 @@ struct msdos_inode_info {
int
i_logstart
;
/* logical first cluster */
int
i_attrs
;
/* unused attribute bits */
int
i_ctime_ms
;
/* unused change time in milliseconds */
int
i_location
;
/* on-disk position of directory entry or 0 */
loff_t
i_pos
;
/* on-disk position of directory entry or 0 */
struct
list_head
i_fat_hash
;
/* hash by i_location */
struct
inode
vfs_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