Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
b5f5914c
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
b5f5914c
编写于
8月 18, 2015
作者:
A
Al Viro
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'ufs' into for-next
上级
15cf3b7a
4e317ce7
变更
6
展开全部
隐藏空白更改
内联
并排
Showing
6 changed file
with
644 addition
and
882 deletion
+644
-882
fs/ufs/Makefile
fs/ufs/Makefile
+1
-1
fs/ufs/balloc.c
fs/ufs/balloc.c
+4
-0
fs/ufs/inode.c
fs/ufs/inode.c
+632
-316
fs/ufs/super.c
fs/ufs/super.c
+4
-32
fs/ufs/truncate.c
fs/ufs/truncate.c
+0
-523
fs/ufs/ufs.h
fs/ufs/ufs.h
+3
-10
未找到文件。
fs/ufs/Makefile
浏览文件 @
b5f5914c
...
@@ -5,5 +5,5 @@
...
@@ -5,5 +5,5 @@
obj-$(CONFIG_UFS_FS)
+=
ufs.o
obj-$(CONFIG_UFS_FS)
+=
ufs.o
ufs-objs
:=
balloc.o cylinder.o dir.o file.o ialloc.o inode.o
\
ufs-objs
:=
balloc.o cylinder.o dir.o file.o ialloc.o inode.o
\
namei.o super.o symlink.o
truncate.o
util.o
namei.o super.o symlink.o util.o
ccflags-$(CONFIG_UFS_DEBUG)
+=
-DDEBUG
ccflags-$(CONFIG_UFS_DEBUG)
+=
-DDEBUG
fs/ufs/balloc.c
浏览文件 @
b5f5914c
...
@@ -417,7 +417,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
...
@@ -417,7 +417,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
if
(
oldcount
==
0
)
{
if
(
oldcount
==
0
)
{
result
=
ufs_alloc_fragments
(
inode
,
cgno
,
goal
,
count
,
err
);
result
=
ufs_alloc_fragments
(
inode
,
cgno
,
goal
,
count
,
err
);
if
(
result
)
{
if
(
result
)
{
write_seqlock
(
&
UFS_I
(
inode
)
->
meta_lock
);
ufs_cpu_to_data_ptr
(
sb
,
p
,
result
);
ufs_cpu_to_data_ptr
(
sb
,
p
,
result
);
write_sequnlock
(
&
UFS_I
(
inode
)
->
meta_lock
);
*
err
=
0
;
*
err
=
0
;
UFS_I
(
inode
)
->
i_lastfrag
=
UFS_I
(
inode
)
->
i_lastfrag
=
max
(
UFS_I
(
inode
)
->
i_lastfrag
,
fragment
+
count
);
max
(
UFS_I
(
inode
)
->
i_lastfrag
,
fragment
+
count
);
...
@@ -473,7 +475,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
...
@@ -473,7 +475,9 @@ u64 ufs_new_fragments(struct inode *inode, void *p, u64 fragment,
ufs_change_blocknr
(
inode
,
fragment
-
oldcount
,
oldcount
,
ufs_change_blocknr
(
inode
,
fragment
-
oldcount
,
oldcount
,
uspi
->
s_sbbase
+
tmp
,
uspi
->
s_sbbase
+
tmp
,
uspi
->
s_sbbase
+
result
,
locked_page
);
uspi
->
s_sbbase
+
result
,
locked_page
);
write_seqlock
(
&
UFS_I
(
inode
)
->
meta_lock
);
ufs_cpu_to_data_ptr
(
sb
,
p
,
result
);
ufs_cpu_to_data_ptr
(
sb
,
p
,
result
);
write_sequnlock
(
&
UFS_I
(
inode
)
->
meta_lock
);
*
err
=
0
;
*
err
=
0
;
UFS_I
(
inode
)
->
i_lastfrag
=
max
(
UFS_I
(
inode
)
->
i_lastfrag
,
UFS_I
(
inode
)
->
i_lastfrag
=
max
(
UFS_I
(
inode
)
->
i_lastfrag
,
fragment
+
count
);
fragment
+
count
);
...
...
fs/ufs/inode.c
浏览文件 @
b5f5914c
此差异已折叠。
点击以展开。
fs/ufs/super.c
浏览文件 @
b5f5914c
...
@@ -94,22 +94,6 @@
...
@@ -94,22 +94,6 @@
#include "swab.h"
#include "swab.h"
#include "util.h"
#include "util.h"
void
lock_ufs
(
struct
super_block
*
sb
)
{
struct
ufs_sb_info
*
sbi
=
UFS_SB
(
sb
);
mutex_lock
(
&
sbi
->
mutex
);
sbi
->
mutex_owner
=
current
;
}
void
unlock_ufs
(
struct
super_block
*
sb
)
{
struct
ufs_sb_info
*
sbi
=
UFS_SB
(
sb
);
sbi
->
mutex_owner
=
NULL
;
mutex_unlock
(
&
sbi
->
mutex
);
}
static
struct
inode
*
ufs_nfs_get_inode
(
struct
super_block
*
sb
,
u64
ino
,
u32
generation
)
static
struct
inode
*
ufs_nfs_get_inode
(
struct
super_block
*
sb
,
u64
ino
,
u32
generation
)
{
{
struct
ufs_sb_private_info
*
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
struct
ufs_sb_private_info
*
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
...
@@ -694,7 +678,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
...
@@ -694,7 +678,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
struct
ufs_super_block_third
*
usb3
;
struct
ufs_super_block_third
*
usb3
;
unsigned
flags
;
unsigned
flags
;
lock_ufs
(
sb
);
mutex_lock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_lock
(
&
UFS_SB
(
sb
)
->
s_lock
);
UFSD
(
"ENTER
\n
"
);
UFSD
(
"ENTER
\n
"
);
...
@@ -714,7 +697,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
...
@@ -714,7 +697,6 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
UFSD
(
"EXIT
\n
"
);
UFSD
(
"EXIT
\n
"
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
0
;
return
0
;
}
}
...
@@ -758,7 +740,6 @@ static void ufs_put_super(struct super_block *sb)
...
@@ -758,7 +740,6 @@ static void ufs_put_super(struct super_block *sb)
ubh_brelse_uspi
(
sbi
->
s_uspi
);
ubh_brelse_uspi
(
sbi
->
s_uspi
);
kfree
(
sbi
->
s_uspi
);
kfree
(
sbi
->
s_uspi
);
mutex_destroy
(
&
sbi
->
mutex
);
kfree
(
sbi
);
kfree
(
sbi
);
sb
->
s_fs_info
=
NULL
;
sb
->
s_fs_info
=
NULL
;
UFSD
(
"EXIT
\n
"
);
UFSD
(
"EXIT
\n
"
);
...
@@ -801,7 +782,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
...
@@ -801,7 +782,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
UFSD
(
"flag %u
\n
"
,
(
int
)(
sb
->
s_flags
&
MS_RDONLY
));
UFSD
(
"flag %u
\n
"
,
(
int
)(
sb
->
s_flags
&
MS_RDONLY
));
mutex_init
(
&
sbi
->
mutex
);
mutex_init
(
&
sbi
->
s_lock
);
mutex_init
(
&
sbi
->
s_lock
);
spin_lock_init
(
&
sbi
->
work_lock
);
spin_lock_init
(
&
sbi
->
work_lock
);
INIT_DELAYED_WORK
(
&
sbi
->
sync_work
,
delayed_sync_fs
);
INIT_DELAYED_WORK
(
&
sbi
->
sync_work
,
delayed_sync_fs
);
...
@@ -1257,7 +1237,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
...
@@ -1257,7 +1237,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
return
0
;
return
0
;
failed:
failed:
mutex_destroy
(
&
sbi
->
mutex
);
if
(
ubh
)
if
(
ubh
)
ubh_brelse_uspi
(
uspi
);
ubh_brelse_uspi
(
uspi
);
kfree
(
uspi
);
kfree
(
uspi
);
...
@@ -1280,7 +1259,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
...
@@ -1280,7 +1259,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
unsigned
flags
;
unsigned
flags
;
sync_filesystem
(
sb
);
sync_filesystem
(
sb
);
lock_ufs
(
sb
);
mutex_lock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_lock
(
&
UFS_SB
(
sb
)
->
s_lock
);
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
flags
=
UFS_SB
(
sb
)
->
s_flags
;
flags
=
UFS_SB
(
sb
)
->
s_flags
;
...
@@ -1296,7 +1274,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
...
@@ -1296,7 +1274,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
ufs_set_opt
(
new_mount_opt
,
ONERROR_LOCK
);
ufs_set_opt
(
new_mount_opt
,
ONERROR_LOCK
);
if
(
!
ufs_parse_options
(
data
,
&
new_mount_opt
))
{
if
(
!
ufs_parse_options
(
data
,
&
new_mount_opt
))
{
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
!
(
new_mount_opt
&
UFS_MOUNT_UFSTYPE
))
{
if
(
!
(
new_mount_opt
&
UFS_MOUNT_UFSTYPE
))
{
...
@@ -1304,14 +1281,12 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
...
@@ -1304,14 +1281,12 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
}
else
if
((
new_mount_opt
&
UFS_MOUNT_UFSTYPE
)
!=
ufstype
)
{
}
else
if
((
new_mount_opt
&
UFS_MOUNT_UFSTYPE
)
!=
ufstype
)
{
pr_err
(
"ufstype can't be changed during remount
\n
"
);
pr_err
(
"ufstype can't be changed during remount
\n
"
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
((
*
mount_flags
&
MS_RDONLY
)
==
(
sb
->
s_flags
&
MS_RDONLY
))
{
if
((
*
mount_flags
&
MS_RDONLY
)
==
(
sb
->
s_flags
&
MS_RDONLY
))
{
UFS_SB
(
sb
)
->
s_mount_opt
=
new_mount_opt
;
UFS_SB
(
sb
)
->
s_mount_opt
=
new_mount_opt
;
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
0
;
return
0
;
}
}
...
@@ -1335,7 +1310,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
...
@@ -1335,7 +1310,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
#ifndef CONFIG_UFS_FS_WRITE
#ifndef CONFIG_UFS_FS_WRITE
pr_err
(
"ufs was compiled with read-only support, can't be mounted as read-write
\n
"
);
pr_err
(
"ufs was compiled with read-only support, can't be mounted as read-write
\n
"
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
-
EINVAL
;
return
-
EINVAL
;
#else
#else
if
(
ufstype
!=
UFS_MOUNT_UFSTYPE_SUN
&&
if
(
ufstype
!=
UFS_MOUNT_UFSTYPE_SUN
&&
...
@@ -1345,13 +1319,11 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
...
@@ -1345,13 +1319,11 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
ufstype
!=
UFS_MOUNT_UFSTYPE_UFS2
)
{
ufstype
!=
UFS_MOUNT_UFSTYPE_UFS2
)
{
pr_err
(
"this ufstype is read-only supported
\n
"
);
pr_err
(
"this ufstype is read-only supported
\n
"
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
!
ufs_read_cylinder_structures
(
sb
))
{
if
(
!
ufs_read_cylinder_structures
(
sb
))
{
pr_err
(
"failed during remounting
\n
"
);
pr_err
(
"failed during remounting
\n
"
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
-
EPERM
;
return
-
EPERM
;
}
}
sb
->
s_flags
&=
~
MS_RDONLY
;
sb
->
s_flags
&=
~
MS_RDONLY
;
...
@@ -1359,7 +1331,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
...
@@ -1359,7 +1331,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
}
}
UFS_SB
(
sb
)
->
s_mount_opt
=
new_mount_opt
;
UFS_SB
(
sb
)
->
s_mount_opt
=
new_mount_opt
;
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
unlock_ufs
(
sb
);
return
0
;
return
0
;
}
}
...
@@ -1391,8 +1362,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
...
@@ -1391,8 +1362,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
struct
ufs_super_block_third
*
usb3
;
struct
ufs_super_block_third
*
usb3
;
u64
id
=
huge_encode_dev
(
sb
->
s_bdev
->
bd_dev
);
u64
id
=
huge_encode_dev
(
sb
->
s_bdev
->
bd_dev
);
lock_ufs
(
sb
);
mutex_lock
(
&
UFS_SB
(
sb
)
->
s_lock
);
usb3
=
ubh_get_usb_third
(
uspi
);
usb3
=
ubh_get_usb_third
(
uspi
);
if
((
flags
&
UFS_TYPE_MASK
)
==
UFS_TYPE_UFS2
)
{
if
((
flags
&
UFS_TYPE_MASK
)
==
UFS_TYPE_UFS2
)
{
...
@@ -1413,7 +1383,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
...
@@ -1413,7 +1383,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
buf
->
f_fsid
.
val
[
0
]
=
(
u32
)
id
;
buf
->
f_fsid
.
val
[
0
]
=
(
u32
)
id
;
buf
->
f_fsid
.
val
[
1
]
=
(
u32
)(
id
>>
32
);
buf
->
f_fsid
.
val
[
1
]
=
(
u32
)(
id
>>
32
);
unlock_ufs
(
sb
);
mutex_unlock
(
&
UFS_SB
(
sb
)
->
s_lock
);
return
0
;
return
0
;
}
}
...
@@ -1429,6 +1399,8 @@ static struct inode *ufs_alloc_inode(struct super_block *sb)
...
@@ -1429,6 +1399,8 @@ static struct inode *ufs_alloc_inode(struct super_block *sb)
return
NULL
;
return
NULL
;
ei
->
vfs_inode
.
i_version
=
1
;
ei
->
vfs_inode
.
i_version
=
1
;
seqlock_init
(
&
ei
->
meta_lock
);
mutex_init
(
&
ei
->
truncate_mutex
);
return
&
ei
->
vfs_inode
;
return
&
ei
->
vfs_inode
;
}
}
...
...
fs/ufs/truncate.c
已删除
100644 → 0
浏览文件 @
15cf3b7a
/*
* linux/fs/ufs/truncate.c
*
* Copyright (C) 1998
* Daniel Pirkl <daniel.pirkl@email.cz>
* Charles University, Faculty of Mathematics and Physics
*
* from
*
* linux/fs/ext2/truncate.c
*
* Copyright (C) 1992, 1993, 1994, 1995
* Remy Card (card@masi.ibp.fr)
* Laboratoire MASI - Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* from
*
* linux/fs/minix/truncate.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Big-endian to little-endian byte-swapping/bitmaps by
* David S. Miller (davem@caip.rutgers.edu), 1995
*/
/*
* Real random numbers for secure rm added 94/02/18
* Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
*/
/*
* Adoptation to use page cache and UFS2 write support by
* Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007
*/
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/time.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
#include <linux/sched.h>
#include "ufs_fs.h"
#include "ufs.h"
#include "swab.h"
#include "util.h"
/*
* Secure deletion currently doesn't work. It interacts very badly
* with buffers shared with memory mappings, and for that reason
* can't be done in the truncate() routines. It should instead be
* done separately in "release()" before calling the truncate routines
* that will release the actual file blocks.
*
* Linus
*/
#define DIRECT_BLOCK ((inode->i_size + uspi->s_bsize - 1) >> uspi->s_bshift)
#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
static
int
ufs_trunc_direct
(
struct
inode
*
inode
)
{
struct
ufs_inode_info
*
ufsi
=
UFS_I
(
inode
);
struct
super_block
*
sb
;
struct
ufs_sb_private_info
*
uspi
;
void
*
p
;
u64
frag1
,
frag2
,
frag3
,
frag4
,
block1
,
block2
;
unsigned
frag_to_free
,
free_count
;
unsigned
i
,
tmp
;
int
retry
;
UFSD
(
"ENTER: ino %lu
\n
"
,
inode
->
i_ino
);
sb
=
inode
->
i_sb
;
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
frag_to_free
=
0
;
free_count
=
0
;
retry
=
0
;
frag1
=
DIRECT_FRAGMENT
;
frag4
=
min_t
(
u64
,
UFS_NDIR_FRAGMENT
,
ufsi
->
i_lastfrag
);
frag2
=
((
frag1
&
uspi
->
s_fpbmask
)
?
((
frag1
|
uspi
->
s_fpbmask
)
+
1
)
:
frag1
);
frag3
=
frag4
&
~
uspi
->
s_fpbmask
;
block1
=
block2
=
0
;
if
(
frag2
>
frag3
)
{
frag2
=
frag4
;
frag3
=
frag4
=
0
;
}
else
if
(
frag2
<
frag3
)
{
block1
=
ufs_fragstoblks
(
frag2
);
block2
=
ufs_fragstoblks
(
frag3
);
}
UFSD
(
"ino %lu, frag1 %llu, frag2 %llu, block1 %llu, block2 %llu,"
" frag3 %llu, frag4 %llu
\n
"
,
inode
->
i_ino
,
(
unsigned
long
long
)
frag1
,
(
unsigned
long
long
)
frag2
,
(
unsigned
long
long
)
block1
,
(
unsigned
long
long
)
block2
,
(
unsigned
long
long
)
frag3
,
(
unsigned
long
long
)
frag4
);
if
(
frag1
>=
frag2
)
goto
next1
;
/*
* Free first free fragments
*/
p
=
ufs_get_direct_data_ptr
(
uspi
,
ufsi
,
ufs_fragstoblks
(
frag1
));
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
if
(
!
tmp
)
ufs_panic
(
sb
,
"ufs_trunc_direct"
,
"internal error"
);
frag2
-=
frag1
;
frag1
=
ufs_fragnum
(
frag1
);
ufs_free_fragments
(
inode
,
tmp
+
frag1
,
frag2
);
mark_inode_dirty
(
inode
);
frag_to_free
=
tmp
+
frag1
;
next1:
/*
* Free whole blocks
*/
for
(
i
=
block1
;
i
<
block2
;
i
++
)
{
p
=
ufs_get_direct_data_ptr
(
uspi
,
ufsi
,
i
);
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
if
(
!
tmp
)
continue
;
ufs_data_ptr_clear
(
uspi
,
p
);
if
(
free_count
==
0
)
{
frag_to_free
=
tmp
;
free_count
=
uspi
->
s_fpb
;
}
else
if
(
free_count
>
0
&&
frag_to_free
==
tmp
-
free_count
)
free_count
+=
uspi
->
s_fpb
;
else
{
ufs_free_blocks
(
inode
,
frag_to_free
,
free_count
);
frag_to_free
=
tmp
;
free_count
=
uspi
->
s_fpb
;
}
mark_inode_dirty
(
inode
);
}
if
(
free_count
>
0
)
ufs_free_blocks
(
inode
,
frag_to_free
,
free_count
);
if
(
frag3
>=
frag4
)
goto
next3
;
/*
* Free last free fragments
*/
p
=
ufs_get_direct_data_ptr
(
uspi
,
ufsi
,
ufs_fragstoblks
(
frag3
));
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
if
(
!
tmp
)
ufs_panic
(
sb
,
"ufs_truncate_direct"
,
"internal error"
);
frag4
=
ufs_fragnum
(
frag4
);
ufs_data_ptr_clear
(
uspi
,
p
);
ufs_free_fragments
(
inode
,
tmp
,
frag4
);
mark_inode_dirty
(
inode
);
next3:
UFSD
(
"EXIT: ino %lu
\n
"
,
inode
->
i_ino
);
return
retry
;
}
static
int
ufs_trunc_indirect
(
struct
inode
*
inode
,
u64
offset
,
void
*
p
)
{
struct
super_block
*
sb
;
struct
ufs_sb_private_info
*
uspi
;
struct
ufs_buffer_head
*
ind_ubh
;
void
*
ind
;
u64
tmp
,
indirect_block
,
i
,
frag_to_free
;
unsigned
free_count
;
int
retry
;
UFSD
(
"ENTER: ino %lu, offset %llu, p: %p
\n
"
,
inode
->
i_ino
,
(
unsigned
long
long
)
offset
,
p
);
BUG_ON
(
!
p
);
sb
=
inode
->
i_sb
;
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
frag_to_free
=
0
;
free_count
=
0
;
retry
=
0
;
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
if
(
!
tmp
)
return
0
;
ind_ubh
=
ubh_bread
(
sb
,
tmp
,
uspi
->
s_bsize
);
if
(
tmp
!=
ufs_data_ptr_to_cpu
(
sb
,
p
))
{
ubh_brelse
(
ind_ubh
);
return
1
;
}
if
(
!
ind_ubh
)
{
ufs_data_ptr_clear
(
uspi
,
p
);
return
0
;
}
indirect_block
=
(
DIRECT_BLOCK
>
offset
)
?
(
DIRECT_BLOCK
-
offset
)
:
0
;
for
(
i
=
indirect_block
;
i
<
uspi
->
s_apb
;
i
++
)
{
ind
=
ubh_get_data_ptr
(
uspi
,
ind_ubh
,
i
);
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
ind
);
if
(
!
tmp
)
continue
;
ufs_data_ptr_clear
(
uspi
,
ind
);
ubh_mark_buffer_dirty
(
ind_ubh
);
if
(
free_count
==
0
)
{
frag_to_free
=
tmp
;
free_count
=
uspi
->
s_fpb
;
}
else
if
(
free_count
>
0
&&
frag_to_free
==
tmp
-
free_count
)
free_count
+=
uspi
->
s_fpb
;
else
{
ufs_free_blocks
(
inode
,
frag_to_free
,
free_count
);
frag_to_free
=
tmp
;
free_count
=
uspi
->
s_fpb
;
}
mark_inode_dirty
(
inode
);
}
if
(
free_count
>
0
)
{
ufs_free_blocks
(
inode
,
frag_to_free
,
free_count
);
}
for
(
i
=
0
;
i
<
uspi
->
s_apb
;
i
++
)
if
(
!
ufs_is_data_ptr_zero
(
uspi
,
ubh_get_data_ptr
(
uspi
,
ind_ubh
,
i
)))
break
;
if
(
i
>=
uspi
->
s_apb
)
{
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
ufs_data_ptr_clear
(
uspi
,
p
);
ufs_free_blocks
(
inode
,
tmp
,
uspi
->
s_fpb
);
mark_inode_dirty
(
inode
);
ubh_bforget
(
ind_ubh
);
ind_ubh
=
NULL
;
}
if
(
IS_SYNC
(
inode
)
&&
ind_ubh
&&
ubh_buffer_dirty
(
ind_ubh
))
ubh_sync_block
(
ind_ubh
);
ubh_brelse
(
ind_ubh
);
UFSD
(
"EXIT: ino %lu
\n
"
,
inode
->
i_ino
);
return
retry
;
}
static
int
ufs_trunc_dindirect
(
struct
inode
*
inode
,
u64
offset
,
void
*
p
)
{
struct
super_block
*
sb
;
struct
ufs_sb_private_info
*
uspi
;
struct
ufs_buffer_head
*
dind_bh
;
u64
i
,
tmp
,
dindirect_block
;
void
*
dind
;
int
retry
=
0
;
UFSD
(
"ENTER: ino %lu
\n
"
,
inode
->
i_ino
);
sb
=
inode
->
i_sb
;
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
dindirect_block
=
(
DIRECT_BLOCK
>
offset
)
?
((
DIRECT_BLOCK
-
offset
)
>>
uspi
->
s_apbshift
)
:
0
;
retry
=
0
;
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
if
(
!
tmp
)
return
0
;
dind_bh
=
ubh_bread
(
sb
,
tmp
,
uspi
->
s_bsize
);
if
(
tmp
!=
ufs_data_ptr_to_cpu
(
sb
,
p
))
{
ubh_brelse
(
dind_bh
);
return
1
;
}
if
(
!
dind_bh
)
{
ufs_data_ptr_clear
(
uspi
,
p
);
return
0
;
}
for
(
i
=
dindirect_block
;
i
<
uspi
->
s_apb
;
i
++
)
{
dind
=
ubh_get_data_ptr
(
uspi
,
dind_bh
,
i
);
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
dind
);
if
(
!
tmp
)
continue
;
retry
|=
ufs_trunc_indirect
(
inode
,
offset
+
(
i
<<
uspi
->
s_apbshift
),
dind
);
ubh_mark_buffer_dirty
(
dind_bh
);
}
for
(
i
=
0
;
i
<
uspi
->
s_apb
;
i
++
)
if
(
!
ufs_is_data_ptr_zero
(
uspi
,
ubh_get_data_ptr
(
uspi
,
dind_bh
,
i
)))
break
;
if
(
i
>=
uspi
->
s_apb
)
{
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
ufs_data_ptr_clear
(
uspi
,
p
);
ufs_free_blocks
(
inode
,
tmp
,
uspi
->
s_fpb
);
mark_inode_dirty
(
inode
);
ubh_bforget
(
dind_bh
);
dind_bh
=
NULL
;
}
if
(
IS_SYNC
(
inode
)
&&
dind_bh
&&
ubh_buffer_dirty
(
dind_bh
))
ubh_sync_block
(
dind_bh
);
ubh_brelse
(
dind_bh
);
UFSD
(
"EXIT: ino %lu
\n
"
,
inode
->
i_ino
);
return
retry
;
}
static
int
ufs_trunc_tindirect
(
struct
inode
*
inode
)
{
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
ufs_sb_private_info
*
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
struct
ufs_inode_info
*
ufsi
=
UFS_I
(
inode
);
struct
ufs_buffer_head
*
tind_bh
;
u64
tindirect_block
,
tmp
,
i
;
void
*
tind
,
*
p
;
int
retry
;
UFSD
(
"ENTER: ino %lu
\n
"
,
inode
->
i_ino
);
retry
=
0
;
tindirect_block
=
(
DIRECT_BLOCK
>
(
UFS_NDADDR
+
uspi
->
s_apb
+
uspi
->
s_2apb
))
?
((
DIRECT_BLOCK
-
UFS_NDADDR
-
uspi
->
s_apb
-
uspi
->
s_2apb
)
>>
uspi
->
s_2apbshift
)
:
0
;
p
=
ufs_get_direct_data_ptr
(
uspi
,
ufsi
,
UFS_TIND_BLOCK
);
if
(
!
(
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
)))
return
0
;
tind_bh
=
ubh_bread
(
sb
,
tmp
,
uspi
->
s_bsize
);
if
(
tmp
!=
ufs_data_ptr_to_cpu
(
sb
,
p
))
{
ubh_brelse
(
tind_bh
);
return
1
;
}
if
(
!
tind_bh
)
{
ufs_data_ptr_clear
(
uspi
,
p
);
return
0
;
}
for
(
i
=
tindirect_block
;
i
<
uspi
->
s_apb
;
i
++
)
{
tind
=
ubh_get_data_ptr
(
uspi
,
tind_bh
,
i
);
retry
|=
ufs_trunc_dindirect
(
inode
,
UFS_NDADDR
+
uspi
->
s_apb
+
((
i
+
1
)
<<
uspi
->
s_2apbshift
),
tind
);
ubh_mark_buffer_dirty
(
tind_bh
);
}
for
(
i
=
0
;
i
<
uspi
->
s_apb
;
i
++
)
if
(
!
ufs_is_data_ptr_zero
(
uspi
,
ubh_get_data_ptr
(
uspi
,
tind_bh
,
i
)))
break
;
if
(
i
>=
uspi
->
s_apb
)
{
tmp
=
ufs_data_ptr_to_cpu
(
sb
,
p
);
ufs_data_ptr_clear
(
uspi
,
p
);
ufs_free_blocks
(
inode
,
tmp
,
uspi
->
s_fpb
);
mark_inode_dirty
(
inode
);
ubh_bforget
(
tind_bh
);
tind_bh
=
NULL
;
}
if
(
IS_SYNC
(
inode
)
&&
tind_bh
&&
ubh_buffer_dirty
(
tind_bh
))
ubh_sync_block
(
tind_bh
);
ubh_brelse
(
tind_bh
);
UFSD
(
"EXIT: ino %lu
\n
"
,
inode
->
i_ino
);
return
retry
;
}
static
int
ufs_alloc_lastblock
(
struct
inode
*
inode
)
{
int
err
=
0
;
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
address_space
*
mapping
=
inode
->
i_mapping
;
struct
ufs_sb_private_info
*
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
unsigned
i
,
end
;
sector_t
lastfrag
;
struct
page
*
lastpage
;
struct
buffer_head
*
bh
;
u64
phys64
;
lastfrag
=
(
i_size_read
(
inode
)
+
uspi
->
s_fsize
-
1
)
>>
uspi
->
s_fshift
;
if
(
!
lastfrag
)
goto
out
;
lastfrag
--
;
lastpage
=
ufs_get_locked_page
(
mapping
,
lastfrag
>>
(
PAGE_CACHE_SHIFT
-
inode
->
i_blkbits
));
if
(
IS_ERR
(
lastpage
))
{
err
=
-
EIO
;
goto
out
;
}
end
=
lastfrag
&
((
1
<<
(
PAGE_CACHE_SHIFT
-
inode
->
i_blkbits
))
-
1
);
bh
=
page_buffers
(
lastpage
);
for
(
i
=
0
;
i
<
end
;
++
i
)
bh
=
bh
->
b_this_page
;
err
=
ufs_getfrag_block
(
inode
,
lastfrag
,
bh
,
1
);
if
(
unlikely
(
err
))
goto
out_unlock
;
if
(
buffer_new
(
bh
))
{
clear_buffer_new
(
bh
);
unmap_underlying_metadata
(
bh
->
b_bdev
,
bh
->
b_blocknr
);
/*
* we do not zeroize fragment, because of
* if it maped to hole, it already contains zeroes
*/
set_buffer_uptodate
(
bh
);
mark_buffer_dirty
(
bh
);
set_page_dirty
(
lastpage
);
}
if
(
lastfrag
>=
UFS_IND_FRAGMENT
)
{
end
=
uspi
->
s_fpb
-
ufs_fragnum
(
lastfrag
)
-
1
;
phys64
=
bh
->
b_blocknr
+
1
;
for
(
i
=
0
;
i
<
end
;
++
i
)
{
bh
=
sb_getblk
(
sb
,
i
+
phys64
);
lock_buffer
(
bh
);
memset
(
bh
->
b_data
,
0
,
sb
->
s_blocksize
);
set_buffer_uptodate
(
bh
);
mark_buffer_dirty
(
bh
);
unlock_buffer
(
bh
);
sync_dirty_buffer
(
bh
);
brelse
(
bh
);
}
}
out_unlock:
ufs_put_locked_page
(
lastpage
);
out:
return
err
;
}
int
ufs_truncate
(
struct
inode
*
inode
,
loff_t
old_i_size
)
{
struct
ufs_inode_info
*
ufsi
=
UFS_I
(
inode
);
struct
super_block
*
sb
=
inode
->
i_sb
;
struct
ufs_sb_private_info
*
uspi
=
UFS_SB
(
sb
)
->
s_uspi
;
int
retry
,
err
=
0
;
UFSD
(
"ENTER: ino %lu, i_size: %llu, old_i_size: %llu
\n
"
,
inode
->
i_ino
,
(
unsigned
long
long
)
i_size_read
(
inode
),
(
unsigned
long
long
)
old_i_size
);
if
(
!
(
S_ISREG
(
inode
->
i_mode
)
||
S_ISDIR
(
inode
->
i_mode
)
||
S_ISLNK
(
inode
->
i_mode
)))
return
-
EINVAL
;
if
(
IS_APPEND
(
inode
)
||
IS_IMMUTABLE
(
inode
))
return
-
EPERM
;
err
=
ufs_alloc_lastblock
(
inode
);
if
(
err
)
{
i_size_write
(
inode
,
old_i_size
);
goto
out
;
}
block_truncate_page
(
inode
->
i_mapping
,
inode
->
i_size
,
ufs_getfrag_block
);
while
(
1
)
{
retry
=
ufs_trunc_direct
(
inode
);
retry
|=
ufs_trunc_indirect
(
inode
,
UFS_IND_BLOCK
,
ufs_get_direct_data_ptr
(
uspi
,
ufsi
,
UFS_IND_BLOCK
));
retry
|=
ufs_trunc_dindirect
(
inode
,
UFS_IND_BLOCK
+
uspi
->
s_apb
,
ufs_get_direct_data_ptr
(
uspi
,
ufsi
,
UFS_DIND_BLOCK
));
retry
|=
ufs_trunc_tindirect
(
inode
);
if
(
!
retry
)
break
;
if
(
IS_SYNC
(
inode
)
&&
(
inode
->
i_state
&
I_DIRTY
))
ufs_sync_inode
(
inode
);
yield
();
}
inode
->
i_mtime
=
inode
->
i_ctime
=
CURRENT_TIME_SEC
;
ufsi
->
i_lastfrag
=
DIRECT_FRAGMENT
;
mark_inode_dirty
(
inode
);
out:
UFSD
(
"EXIT: err %d
\n
"
,
err
);
return
err
;
}
int
ufs_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
attr
)
{
struct
inode
*
inode
=
d_inode
(
dentry
);
unsigned
int
ia_valid
=
attr
->
ia_valid
;
int
error
;
error
=
inode_change_ok
(
inode
,
attr
);
if
(
error
)
return
error
;
if
(
ia_valid
&
ATTR_SIZE
&&
attr
->
ia_size
!=
inode
->
i_size
)
{
loff_t
old_i_size
=
inode
->
i_size
;
/* XXX(truncate): truncate_setsize should be called last */
truncate_setsize
(
inode
,
attr
->
ia_size
);
lock_ufs
(
inode
->
i_sb
);
error
=
ufs_truncate
(
inode
,
old_i_size
);
unlock_ufs
(
inode
->
i_sb
);
if
(
error
)
return
error
;
}
setattr_copy
(
inode
,
attr
);
mark_inode_dirty
(
inode
);
return
0
;
}
const
struct
inode_operations
ufs_file_inode_operations
=
{
.
setattr
=
ufs_setattr
,
};
fs/ufs/ufs.h
浏览文件 @
b5f5914c
...
@@ -24,8 +24,6 @@ struct ufs_sb_info {
...
@@ -24,8 +24,6 @@ struct ufs_sb_info {
unsigned
s_cgno
[
UFS_MAX_GROUP_LOADED
];
unsigned
s_cgno
[
UFS_MAX_GROUP_LOADED
];
unsigned
short
s_cg_loaded
;
unsigned
short
s_cg_loaded
;
unsigned
s_mount_opt
;
unsigned
s_mount_opt
;
struct
mutex
mutex
;
struct
task_struct
*
mutex_owner
;
struct
super_block
*
sb
;
struct
super_block
*
sb
;
int
work_queued
;
/* non-zero if the delayed work is queued */
int
work_queued
;
/* non-zero if the delayed work is queued */
struct
delayed_work
sync_work
;
/* FS sync delayed work */
struct
delayed_work
sync_work
;
/* FS sync delayed work */
...
@@ -46,6 +44,8 @@ struct ufs_inode_info {
...
@@ -46,6 +44,8 @@ struct ufs_inode_info {
__u32
i_oeftflag
;
__u32
i_oeftflag
;
__u16
i_osync
;
__u16
i_osync
;
__u64
i_lastfrag
;
__u64
i_lastfrag
;
seqlock_t
meta_lock
;
struct
mutex
truncate_mutex
;
__u32
i_dir_start_lookup
;
__u32
i_dir_start_lookup
;
struct
inode
vfs_inode
;
struct
inode
vfs_inode
;
};
};
...
@@ -122,7 +122,7 @@ extern struct inode *ufs_iget(struct super_block *, unsigned long);
...
@@ -122,7 +122,7 @@ extern struct inode *ufs_iget(struct super_block *, unsigned long);
extern
int
ufs_write_inode
(
struct
inode
*
,
struct
writeback_control
*
);
extern
int
ufs_write_inode
(
struct
inode
*
,
struct
writeback_control
*
);
extern
int
ufs_sync_inode
(
struct
inode
*
);
extern
int
ufs_sync_inode
(
struct
inode
*
);
extern
void
ufs_evict_inode
(
struct
inode
*
);
extern
void
ufs_evict_inode
(
struct
inode
*
);
extern
int
ufs_
getfrag_block
(
struct
inode
*
inode
,
sector_t
fragment
,
struct
buffer_head
*
bh_result
,
int
create
);
extern
int
ufs_
setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
attr
);
/* namei.c */
/* namei.c */
extern
const
struct
file_operations
ufs_dir_operations
;
extern
const
struct
file_operations
ufs_dir_operations
;
...
@@ -140,10 +140,6 @@ void ufs_mark_sb_dirty(struct super_block *sb);
...
@@ -140,10 +140,6 @@ void ufs_mark_sb_dirty(struct super_block *sb);
extern
const
struct
inode_operations
ufs_fast_symlink_inode_operations
;
extern
const
struct
inode_operations
ufs_fast_symlink_inode_operations
;
extern
const
struct
inode_operations
ufs_symlink_inode_operations
;
extern
const
struct
inode_operations
ufs_symlink_inode_operations
;
/* truncate.c */
extern
int
ufs_truncate
(
struct
inode
*
,
loff_t
);
extern
int
ufs_setattr
(
struct
dentry
*
dentry
,
struct
iattr
*
attr
);
static
inline
struct
ufs_sb_info
*
UFS_SB
(
struct
super_block
*
sb
)
static
inline
struct
ufs_sb_info
*
UFS_SB
(
struct
super_block
*
sb
)
{
{
return
sb
->
s_fs_info
;
return
sb
->
s_fs_info
;
...
@@ -170,7 +166,4 @@ static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
...
@@ -170,7 +166,4 @@ static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
return
do_div
(
b
,
uspi
->
s_fpg
);
return
do_div
(
b
,
uspi
->
s_fpg
);
}
}
extern
void
lock_ufs
(
struct
super_block
*
sb
);
extern
void
unlock_ufs
(
struct
super_block
*
sb
);
#endif
/* _UFS_UFS_H */
#endif
/* _UFS_UFS_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录