Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gsplhtlxg
clone-Linux
提交
6e48321a
C
clone-Linux
项目概览
gsplhtlxg
/
clone-Linux
通知
2
Star
0
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
clone-Linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6e48321a
编写于
9月 08, 2005
作者:
A
Anton Altaparmakov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
NTFS: Add ntfs_rl_punch_nolock() which punches a caller specified hole into a runlist.
Signed-off-by:
N
Anton Altaparmakov
<
aia21@cantab.net
>
上级
3ffc5a44
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
289 addition
and
0 deletion
+289
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+2
-0
fs/ntfs/runlist.c
fs/ntfs/runlist.c
+284
-0
fs/ntfs/runlist.h
fs/ntfs/runlist.h
+3
-0
未找到文件。
fs/ntfs/ChangeLog
浏览文件 @
6e48321a
...
...
@@ -53,6 +53,8 @@ ToDo/Notes:
pointing this out.
- Change ntfs_rl_truncate_nolock() to throw away the runlist if the new
length is zero.
- Add runlist.[hc]::ntfs_rl_punch_nolock() which punches a caller
specified hole into a runlist.
2.1.23 - Implement extension of resident files and make writing safe as well as
many bug fixes, cleanups, and enhancements...
...
...
fs/ntfs/runlist.c
浏览文件 @
6e48321a
...
...
@@ -1601,4 +1601,288 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist,
return
0
;
}
/**
* ntfs_rl_punch_nolock - punch a hole into a runlist
* @vol: ntfs volume (needed for error output)
* @runlist: runlist to punch a hole into
* @start: starting VCN of the hole to be created
* @length: size of the hole to be created in units of clusters
*
* Punch a hole into the runlist @runlist starting at VCN @start and of size
* @length clusters.
*
* Return 0 on success and -errno on error, in which case @runlist has not been
* modified.
*
* If @start and/or @start + @length are outside the runlist return error code
* -ENOENT.
*
* If the runlist contains unmapped or error elements between @start and @start
* + @length return error code -EINVAL.
*
* Locking: The caller must hold @runlist->lock for writing.
*/
int
ntfs_rl_punch_nolock
(
const
ntfs_volume
*
vol
,
runlist
*
const
runlist
,
const
VCN
start
,
const
s64
length
)
{
const
VCN
end
=
start
+
length
;
s64
delta
;
runlist_element
*
rl
,
*
rl_end
,
*
rl_real_end
,
*
trl
;
int
old_size
;
BOOL
lcn_fixup
=
FALSE
;
ntfs_debug
(
"Entering for start 0x%llx, length 0x%llx."
,
(
long
long
)
start
,
(
long
long
)
length
);
BUG_ON
(
!
runlist
);
BUG_ON
(
start
<
0
);
BUG_ON
(
length
<
0
);
BUG_ON
(
end
<
0
);
rl
=
runlist
->
rl
;
if
(
unlikely
(
!
rl
))
{
if
(
likely
(
!
start
&&
!
length
))
return
0
;
return
-
ENOENT
;
}
/* Find @start in the runlist. */
while
(
likely
(
rl
->
length
&&
start
>=
rl
[
1
].
vcn
))
rl
++
;
rl_end
=
rl
;
/* Find @end in the runlist. */
while
(
likely
(
rl_end
->
length
&&
end
>=
rl_end
[
1
].
vcn
))
{
/* Verify there are no unmapped or error elements. */
if
(
unlikely
(
rl_end
->
lcn
<
LCN_HOLE
))
return
-
EINVAL
;
rl_end
++
;
}
/* Check the last element. */
if
(
unlikely
(
rl_end
->
length
&&
rl_end
->
lcn
<
LCN_HOLE
))
return
-
EINVAL
;
/* This covers @start being out of bounds, too. */
if
(
!
rl_end
->
length
&&
end
>
rl_end
->
vcn
)
return
-
ENOENT
;
if
(
!
length
)
return
0
;
if
(
!
rl
->
length
)
return
-
ENOENT
;
rl_real_end
=
rl_end
;
/* Determine the runlist size. */
while
(
likely
(
rl_real_end
->
length
))
rl_real_end
++
;
old_size
=
rl_real_end
-
runlist
->
rl
+
1
;
/* If @start is in a hole simply extend the hole. */
if
(
rl
->
lcn
==
LCN_HOLE
)
{
/*
* If both @start and @end are in the same sparse run, we are
* done.
*/
if
(
end
<=
rl
[
1
].
vcn
)
{
ntfs_debug
(
"Done (requested hole is already sparse)."
);
return
0
;
}
extend_hole:
/* Extend the hole. */
rl
->
length
=
end
-
rl
->
vcn
;
/* If @end is in a hole, merge it with the current one. */
if
(
rl_end
->
lcn
==
LCN_HOLE
)
{
rl_end
++
;
rl
->
length
=
rl_end
->
vcn
-
rl
->
vcn
;
}
/* We have done the hole. Now deal with the remaining tail. */
rl
++
;
/* Cut out all runlist elements up to @end. */
if
(
rl
<
rl_end
)
memmove
(
rl
,
rl_end
,
(
rl_real_end
-
rl_end
+
1
)
*
sizeof
(
*
rl
));
/* Adjust the beginning of the tail if necessary. */
if
(
end
>
rl
->
vcn
)
{
s64
delta
=
end
-
rl
->
vcn
;
rl
->
vcn
=
end
;
rl
->
length
-=
delta
;
/* Only adjust the lcn if it is real. */
if
(
rl
->
lcn
>=
0
)
rl
->
lcn
+=
delta
;
}
shrink_allocation:
/* Reallocate memory if the allocation changed. */
if
(
rl
<
rl_end
)
{
rl
=
ntfs_rl_realloc
(
runlist
->
rl
,
old_size
,
old_size
-
(
rl_end
-
rl
));
if
(
IS_ERR
(
rl
))
ntfs_warning
(
vol
->
sb
,
"Failed to shrink "
"runlist buffer. This just "
"wastes a bit of memory "
"temporarily so we ignore it "
"and return success."
);
else
runlist
->
rl
=
rl
;
}
ntfs_debug
(
"Done (extend hole)."
);
return
0
;
}
/*
* If @start is at the beginning of a run things are easier as there is
* no need to split the first run.
*/
if
(
start
==
rl
->
vcn
)
{
/*
* @start is at the beginning of a run.
*
* If the previous run is sparse, extend its hole.
*
* If @end is not in the same run, switch the run to be sparse
* and extend the newly created hole.
*
* Thus both of these cases reduce the problem to the above
* case of "@start is in a hole".
*/
if
(
rl
>
runlist
->
rl
&&
(
rl
-
1
)
->
lcn
==
LCN_HOLE
)
{
rl
--
;
goto
extend_hole
;
}
if
(
end
>=
rl
[
1
].
vcn
)
{
rl
->
lcn
=
LCN_HOLE
;
goto
extend_hole
;
}
/*
* The final case is when @end is in the same run as @start.
* For this need to split the run into two. One run for the
* sparse region between the beginning of the old run, i.e.
* @start, and @end and one for the remaining non-sparse
* region, i.e. between @end and the end of the old run.
*/
trl
=
ntfs_rl_realloc
(
runlist
->
rl
,
old_size
,
old_size
+
1
);
if
(
IS_ERR
(
trl
))
goto
enomem_out
;
old_size
++
;
if
(
runlist
->
rl
!=
trl
)
{
rl
=
trl
+
(
rl
-
runlist
->
rl
);
rl_end
=
trl
+
(
rl_end
-
runlist
->
rl
);
rl_real_end
=
trl
+
(
rl_real_end
-
runlist
->
rl
);
runlist
->
rl
=
trl
;
}
split_end:
/* Shift all the runs up by one. */
memmove
(
rl
+
1
,
rl
,
(
rl_real_end
-
rl
+
1
)
*
sizeof
(
*
rl
));
/* Finally, setup the two split runs. */
rl
->
lcn
=
LCN_HOLE
;
rl
->
length
=
length
;
rl
++
;
rl
->
vcn
+=
length
;
/* Only adjust the lcn if it is real. */
if
(
rl
->
lcn
>=
0
||
lcn_fixup
)
rl
->
lcn
+=
length
;
rl
->
length
-=
length
;
ntfs_debug
(
"Done (split one)."
);
return
0
;
}
/*
* @start is neither in a hole nor at the beginning of a run.
*
* If @end is in a hole, things are easier as simply truncating the run
* @start is in to end at @start - 1, deleting all runs after that up
* to @end, and finally extending the beginning of the run @end is in
* to be @start is all that is needed.
*/
if
(
rl_end
->
lcn
==
LCN_HOLE
)
{
/* Truncate the run containing @start. */
rl
->
length
=
start
-
rl
->
vcn
;
rl
++
;
/* Cut out all runlist elements up to @end. */
if
(
rl
<
rl_end
)
memmove
(
rl
,
rl_end
,
(
rl_real_end
-
rl_end
+
1
)
*
sizeof
(
*
rl
));
/* Extend the beginning of the run @end is in to be @start. */
rl
->
vcn
=
start
;
rl
->
length
=
rl
[
1
].
vcn
-
start
;
goto
shrink_allocation
;
}
/*
* If @end is not in a hole there are still two cases to distinguish.
* Either @end is or is not in the same run as @start.
*
* The second case is easier as it can be reduced to an already solved
* problem by truncating the run @start is in to end at @start - 1.
* Then, if @end is in the next run need to split the run into a sparse
* run followed by a non-sparse run (already covered above) and if @end
* is not in the next run switching it to be sparse, again reduces the
* problem to the already covered case of "@start is in a hole".
*/
if
(
end
>=
rl
[
1
].
vcn
)
{
/*
* If @end is not in the next run, reduce the problem to the
* case of "@start is in a hole".
*/
if
(
rl
[
1
].
length
&&
end
>=
rl
[
2
].
vcn
)
{
/* Truncate the run containing @start. */
rl
->
length
=
start
-
rl
->
vcn
;
rl
++
;
rl
->
vcn
=
start
;
rl
->
lcn
=
LCN_HOLE
;
goto
extend_hole
;
}
trl
=
ntfs_rl_realloc
(
runlist
->
rl
,
old_size
,
old_size
+
1
);
if
(
IS_ERR
(
trl
))
goto
enomem_out
;
old_size
++
;
if
(
runlist
->
rl
!=
trl
)
{
rl
=
trl
+
(
rl
-
runlist
->
rl
);
rl_end
=
trl
+
(
rl_end
-
runlist
->
rl
);
rl_real_end
=
trl
+
(
rl_real_end
-
runlist
->
rl
);
runlist
->
rl
=
trl
;
}
/* Truncate the run containing @start. */
rl
->
length
=
start
-
rl
->
vcn
;
rl
++
;
/*
* @end is in the next run, reduce the problem to the case
* where "@start is at the beginning of a run and @end is in
* the same run as @start".
*/
delta
=
rl
->
vcn
-
start
;
rl
->
vcn
=
start
;
if
(
rl
->
lcn
>=
0
)
{
rl
->
lcn
-=
delta
;
/* Need this in case the lcn just became negative. */
lcn_fixup
=
TRUE
;
}
rl
->
length
+=
delta
;
goto
split_end
;
}
/*
* The first case from above, i.e. @end is in the same run as @start.
* We need to split the run into three. One run for the non-sparse
* region between the beginning of the old run and @start, one for the
* sparse region between @start and @end, and one for the remaining
* non-sparse region, i.e. between @end and the end of the old run.
*/
trl
=
ntfs_rl_realloc
(
runlist
->
rl
,
old_size
,
old_size
+
2
);
if
(
IS_ERR
(
trl
))
goto
enomem_out
;
old_size
+=
2
;
if
(
runlist
->
rl
!=
trl
)
{
rl
=
trl
+
(
rl
-
runlist
->
rl
);
rl_end
=
trl
+
(
rl_end
-
runlist
->
rl
);
rl_real_end
=
trl
+
(
rl_real_end
-
runlist
->
rl
);
runlist
->
rl
=
trl
;
}
/* Shift all the runs up by two. */
memmove
(
rl
+
2
,
rl
,
(
rl_real_end
-
rl
+
1
)
*
sizeof
(
*
rl
));
/* Finally, setup the three split runs. */
rl
->
length
=
start
-
rl
->
vcn
;
rl
++
;
rl
->
vcn
=
start
;
rl
->
lcn
=
LCN_HOLE
;
rl
->
length
=
length
;
rl
++
;
delta
=
end
-
rl
->
vcn
;
rl
->
vcn
=
end
;
rl
->
lcn
+=
delta
;
rl
->
length
-=
delta
;
ntfs_debug
(
"Done (split both)."
);
return
0
;
enomem_out:
ntfs_error
(
vol
->
sb
,
"Not enough memory to extend runlist buffer."
);
return
-
ENOMEM
;
}
#endif
/* NTFS_RW */
fs/ntfs/runlist.h
浏览文件 @
6e48321a
...
...
@@ -94,6 +94,9 @@ extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
extern
int
ntfs_rl_truncate_nolock
(
const
ntfs_volume
*
vol
,
runlist
*
const
runlist
,
const
s64
new_length
);
int
ntfs_rl_punch_nolock
(
const
ntfs_volume
*
vol
,
runlist
*
const
runlist
,
const
VCN
start
,
const
s64
length
);
#endif
/* NTFS_RW */
#endif
/* _LINUX_NTFS_RUNLIST_H */
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录