Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
6545b246
cloud-kernel
项目概览
openanolis
/
cloud-kernel
接近 2 年 前同步成功
通知
170
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
6545b246
编写于
1月 05, 2009
作者:
P
Phillip Lougher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Squashfs: inode operations
Signed-off-by:
N
Phillip Lougher
<
phillip@lougher.demon.co.uk
>
上级
fe0bdec6
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
346 addition
and
0 deletion
+346
-0
fs/squashfs/inode.c
fs/squashfs/inode.c
+346
-0
未找到文件。
fs/squashfs/inode.c
0 → 100644
浏览文件 @
6545b246
/*
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
* Phillip Lougher <phillip@lougher.demon.co.uk>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* inode.c
*/
/*
* This file implements code to create and read inodes from disk.
*
* Inodes in Squashfs are identified by a 48-bit inode which encodes the
* location of the compressed metadata block containing the inode, and the byte
* offset into that block where the inode is placed (<block, offset>).
*
* To maximise compression there are different inodes for each file type
* (regular file, directory, device, etc.), the inode contents and length
* varying with the type.
*
* To further maximise compression, two types of regular file inode and
* directory inode are defined: inodes optimised for frequently occurring
* regular files and directories, and extended types where extra
* information has to be stored.
*/
#include <linux/fs.h>
#include <linux/vfs.h>
#include <linux/zlib.h>
#include "squashfs_fs.h"
#include "squashfs_fs_sb.h"
#include "squashfs_fs_i.h"
#include "squashfs.h"
/*
* Initialise VFS inode with the base inode information common to all
* Squashfs inode types. Sqsh_ino contains the unswapped base inode
* off disk.
*/
static
int
squashfs_new_inode
(
struct
super_block
*
sb
,
struct
inode
*
inode
,
struct
squashfs_base_inode
*
sqsh_ino
)
{
int
err
;
err
=
squashfs_get_id
(
sb
,
le16_to_cpu
(
sqsh_ino
->
uid
),
&
inode
->
i_uid
);
if
(
err
)
return
err
;
err
=
squashfs_get_id
(
sb
,
le16_to_cpu
(
sqsh_ino
->
guid
),
&
inode
->
i_gid
);
if
(
err
)
return
err
;
inode
->
i_ino
=
le32_to_cpu
(
sqsh_ino
->
inode_number
);
inode
->
i_mtime
.
tv_sec
=
le32_to_cpu
(
sqsh_ino
->
mtime
);
inode
->
i_atime
.
tv_sec
=
inode
->
i_mtime
.
tv_sec
;
inode
->
i_ctime
.
tv_sec
=
inode
->
i_mtime
.
tv_sec
;
inode
->
i_mode
=
le16_to_cpu
(
sqsh_ino
->
mode
);
inode
->
i_size
=
0
;
return
err
;
}
struct
inode
*
squashfs_iget
(
struct
super_block
*
sb
,
long
long
ino
,
unsigned
int
ino_number
)
{
struct
inode
*
inode
=
iget_locked
(
sb
,
ino_number
);
int
err
;
TRACE
(
"Entered squashfs_iget
\n
"
);
if
(
!
inode
)
return
ERR_PTR
(
-
ENOMEM
);
if
(
!
(
inode
->
i_state
&
I_NEW
))
return
inode
;
err
=
squashfs_read_inode
(
inode
,
ino
);
if
(
err
)
{
iget_failed
(
inode
);
return
ERR_PTR
(
err
);
}
unlock_new_inode
(
inode
);
return
inode
;
}
/*
* Initialise VFS inode by reading inode from inode table (compressed
* metadata). The format and amount of data read depends on type.
*/
int
squashfs_read_inode
(
struct
inode
*
inode
,
long
long
ino
)
{
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
squashfs_sb_info
*
msblk
=
sb
->
s_fs_info
;
u64
block
=
SQUASHFS_INODE_BLK
(
ino
)
+
msblk
->
inode_table
;
int
err
,
type
,
offset
=
SQUASHFS_INODE_OFFSET
(
ino
);
union
squashfs_inode
squashfs_ino
;
struct
squashfs_base_inode
*
sqshb_ino
=
&
squashfs_ino
.
base
;
TRACE
(
"Entered squashfs_read_inode
\n
"
);
/*
* Read inode base common to all inode types.
*/
err
=
squashfs_read_metadata
(
sb
,
sqshb_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqshb_ino
));
if
(
err
<
0
)
goto
failed_read
;
err
=
squashfs_new_inode
(
sb
,
inode
,
sqshb_ino
);
if
(
err
)
goto
failed_read
;
block
=
SQUASHFS_INODE_BLK
(
ino
)
+
msblk
->
inode_table
;
offset
=
SQUASHFS_INODE_OFFSET
(
ino
);
type
=
le16_to_cpu
(
sqshb_ino
->
inode_type
);
switch
(
type
)
{
case
SQUASHFS_REG_TYPE
:
{
unsigned
int
frag_offset
,
frag_size
,
frag
;
u64
frag_blk
;
struct
squashfs_reg_inode
*
sqsh_ino
=
&
squashfs_ino
.
reg
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
frag
=
le32_to_cpu
(
sqsh_ino
->
fragment
);
if
(
frag
!=
SQUASHFS_INVALID_FRAG
)
{
frag_offset
=
le32_to_cpu
(
sqsh_ino
->
offset
);
frag_size
=
squashfs_frag_lookup
(
sb
,
frag
,
&
frag_blk
);
if
(
frag_size
<
0
)
{
err
=
frag_size
;
goto
failed_read
;
}
}
else
{
frag_blk
=
SQUASHFS_INVALID_BLK
;
frag_size
=
0
;
frag_offset
=
0
;
}
inode
->
i_nlink
=
1
;
inode
->
i_size
=
le32_to_cpu
(
sqsh_ino
->
file_size
);
inode
->
i_fop
=
&
generic_ro_fops
;
inode
->
i_mode
|=
S_IFREG
;
inode
->
i_blocks
=
((
inode
->
i_size
-
1
)
>>
9
)
+
1
;
squashfs_i
(
inode
)
->
fragment_block
=
frag_blk
;
squashfs_i
(
inode
)
->
fragment_size
=
frag_size
;
squashfs_i
(
inode
)
->
fragment_offset
=
frag_offset
;
squashfs_i
(
inode
)
->
start
=
le32_to_cpu
(
sqsh_ino
->
start_block
);
squashfs_i
(
inode
)
->
block_list_start
=
block
;
squashfs_i
(
inode
)
->
offset
=
offset
;
inode
->
i_data
.
a_ops
=
&
squashfs_aops
;
TRACE
(
"File inode %x:%x, start_block %llx, block_list_start "
"%llx, offset %x
\n
"
,
SQUASHFS_INODE_BLK
(
ino
),
offset
,
squashfs_i
(
inode
)
->
start
,
block
,
offset
);
break
;
}
case
SQUASHFS_LREG_TYPE
:
{
unsigned
int
frag_offset
,
frag_size
,
frag
;
u64
frag_blk
;
struct
squashfs_lreg_inode
*
sqsh_ino
=
&
squashfs_ino
.
lreg
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
frag
=
le32_to_cpu
(
sqsh_ino
->
fragment
);
if
(
frag
!=
SQUASHFS_INVALID_FRAG
)
{
frag_offset
=
le32_to_cpu
(
sqsh_ino
->
offset
);
frag_size
=
squashfs_frag_lookup
(
sb
,
frag
,
&
frag_blk
);
if
(
frag_size
<
0
)
{
err
=
frag_size
;
goto
failed_read
;
}
}
else
{
frag_blk
=
SQUASHFS_INVALID_BLK
;
frag_size
=
0
;
frag_offset
=
0
;
}
inode
->
i_nlink
=
le32_to_cpu
(
sqsh_ino
->
nlink
);
inode
->
i_size
=
le64_to_cpu
(
sqsh_ino
->
file_size
);
inode
->
i_fop
=
&
generic_ro_fops
;
inode
->
i_mode
|=
S_IFREG
;
inode
->
i_blocks
=
((
inode
->
i_size
-
le64_to_cpu
(
sqsh_ino
->
sparse
)
-
1
)
>>
9
)
+
1
;
squashfs_i
(
inode
)
->
fragment_block
=
frag_blk
;
squashfs_i
(
inode
)
->
fragment_size
=
frag_size
;
squashfs_i
(
inode
)
->
fragment_offset
=
frag_offset
;
squashfs_i
(
inode
)
->
start
=
le64_to_cpu
(
sqsh_ino
->
start_block
);
squashfs_i
(
inode
)
->
block_list_start
=
block
;
squashfs_i
(
inode
)
->
offset
=
offset
;
inode
->
i_data
.
a_ops
=
&
squashfs_aops
;
TRACE
(
"File inode %x:%x, start_block %llx, block_list_start "
"%llx, offset %x
\n
"
,
SQUASHFS_INODE_BLK
(
ino
),
offset
,
squashfs_i
(
inode
)
->
start
,
block
,
offset
);
break
;
}
case
SQUASHFS_DIR_TYPE
:
{
struct
squashfs_dir_inode
*
sqsh_ino
=
&
squashfs_ino
.
dir
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
inode
->
i_nlink
=
le32_to_cpu
(
sqsh_ino
->
nlink
);
inode
->
i_size
=
le16_to_cpu
(
sqsh_ino
->
file_size
);
inode
->
i_op
=
&
squashfs_dir_inode_ops
;
inode
->
i_fop
=
&
squashfs_dir_ops
;
inode
->
i_mode
|=
S_IFDIR
;
squashfs_i
(
inode
)
->
start
=
le32_to_cpu
(
sqsh_ino
->
start_block
);
squashfs_i
(
inode
)
->
offset
=
le16_to_cpu
(
sqsh_ino
->
offset
);
squashfs_i
(
inode
)
->
dir_idx_cnt
=
0
;
squashfs_i
(
inode
)
->
parent
=
le32_to_cpu
(
sqsh_ino
->
parent_inode
);
TRACE
(
"Directory inode %x:%x, start_block %llx, offset %x
\n
"
,
SQUASHFS_INODE_BLK
(
ino
),
offset
,
squashfs_i
(
inode
)
->
start
,
le16_to_cpu
(
sqsh_ino
->
offset
));
break
;
}
case
SQUASHFS_LDIR_TYPE
:
{
struct
squashfs_ldir_inode
*
sqsh_ino
=
&
squashfs_ino
.
ldir
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
inode
->
i_nlink
=
le32_to_cpu
(
sqsh_ino
->
nlink
);
inode
->
i_size
=
le32_to_cpu
(
sqsh_ino
->
file_size
);
inode
->
i_op
=
&
squashfs_dir_inode_ops
;
inode
->
i_fop
=
&
squashfs_dir_ops
;
inode
->
i_mode
|=
S_IFDIR
;
squashfs_i
(
inode
)
->
start
=
le32_to_cpu
(
sqsh_ino
->
start_block
);
squashfs_i
(
inode
)
->
offset
=
le16_to_cpu
(
sqsh_ino
->
offset
);
squashfs_i
(
inode
)
->
dir_idx_start
=
block
;
squashfs_i
(
inode
)
->
dir_idx_offset
=
offset
;
squashfs_i
(
inode
)
->
dir_idx_cnt
=
le16_to_cpu
(
sqsh_ino
->
i_count
);
squashfs_i
(
inode
)
->
parent
=
le32_to_cpu
(
sqsh_ino
->
parent_inode
);
TRACE
(
"Long directory inode %x:%x, start_block %llx, offset "
"%x
\n
"
,
SQUASHFS_INODE_BLK
(
ino
),
offset
,
squashfs_i
(
inode
)
->
start
,
le16_to_cpu
(
sqsh_ino
->
offset
));
break
;
}
case
SQUASHFS_SYMLINK_TYPE
:
case
SQUASHFS_LSYMLINK_TYPE
:
{
struct
squashfs_symlink_inode
*
sqsh_ino
=
&
squashfs_ino
.
symlink
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
inode
->
i_nlink
=
le32_to_cpu
(
sqsh_ino
->
nlink
);
inode
->
i_size
=
le32_to_cpu
(
sqsh_ino
->
symlink_size
);
inode
->
i_op
=
&
page_symlink_inode_operations
;
inode
->
i_data
.
a_ops
=
&
squashfs_symlink_aops
;
inode
->
i_mode
|=
S_IFLNK
;
squashfs_i
(
inode
)
->
start
=
block
;
squashfs_i
(
inode
)
->
offset
=
offset
;
TRACE
(
"Symbolic link inode %x:%x, start_block %llx, offset "
"%x
\n
"
,
SQUASHFS_INODE_BLK
(
ino
),
offset
,
block
,
offset
);
break
;
}
case
SQUASHFS_BLKDEV_TYPE
:
case
SQUASHFS_CHRDEV_TYPE
:
case
SQUASHFS_LBLKDEV_TYPE
:
case
SQUASHFS_LCHRDEV_TYPE
:
{
struct
squashfs_dev_inode
*
sqsh_ino
=
&
squashfs_ino
.
dev
;
unsigned
int
rdev
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
if
(
type
==
SQUASHFS_CHRDEV_TYPE
)
inode
->
i_mode
|=
S_IFCHR
;
else
inode
->
i_mode
|=
S_IFBLK
;
inode
->
i_nlink
=
le32_to_cpu
(
sqsh_ino
->
nlink
);
rdev
=
le32_to_cpu
(
sqsh_ino
->
rdev
);
init_special_inode
(
inode
,
inode
->
i_mode
,
new_decode_dev
(
rdev
));
TRACE
(
"Device inode %x:%x, rdev %x
\n
"
,
SQUASHFS_INODE_BLK
(
ino
),
offset
,
rdev
);
break
;
}
case
SQUASHFS_FIFO_TYPE
:
case
SQUASHFS_SOCKET_TYPE
:
case
SQUASHFS_LFIFO_TYPE
:
case
SQUASHFS_LSOCKET_TYPE
:
{
struct
squashfs_ipc_inode
*
sqsh_ino
=
&
squashfs_ino
.
ipc
;
err
=
squashfs_read_metadata
(
sb
,
sqsh_ino
,
&
block
,
&
offset
,
sizeof
(
*
sqsh_ino
));
if
(
err
<
0
)
goto
failed_read
;
if
(
type
==
SQUASHFS_FIFO_TYPE
)
inode
->
i_mode
|=
S_IFIFO
;
else
inode
->
i_mode
|=
S_IFSOCK
;
inode
->
i_nlink
=
le32_to_cpu
(
sqsh_ino
->
nlink
);
init_special_inode
(
inode
,
inode
->
i_mode
,
0
);
break
;
}
default:
ERROR
(
"Unknown inode type %d in squashfs_iget!
\n
"
,
type
);
return
-
EINVAL
;
}
return
0
;
failed_read:
ERROR
(
"Unable to read inode 0x%llx
\n
"
,
ino
);
return
err
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录