Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
e653879c
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
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看板
提交
e653879c
编写于
1月 24, 2008
作者:
A
Artem Bityutskiy
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
UBI: implement atomic LEB change ioctl
Signed-off-by:
N
Artem Bityutskiy
<
Artem.Bityutskiy@nokia.com
>
上级
86613682
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
183 addition
and
28 deletion
+183
-28
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/cdev.c
+60
-12
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/ubi.h
+23
-4
drivers/mtd/ubi/upd.c
drivers/mtd/ubi/upd.c
+100
-12
未找到文件。
drivers/mtd/ubi/cdev.c
浏览文件 @
e653879c
...
@@ -132,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
...
@@ -132,8 +132,15 @@ static int vol_cdev_release(struct inode *inode, struct file *file)
if
(
vol
->
updating
)
{
if
(
vol
->
updating
)
{
ubi_warn
(
"update of volume %d not finished, volume is damaged"
,
ubi_warn
(
"update of volume %d not finished, volume is damaged"
,
vol
->
vol_id
);
vol
->
vol_id
);
ubi_assert
(
!
vol
->
changing_leb
);
vol
->
updating
=
0
;
vol
->
updating
=
0
;
vfree
(
vol
->
upd_buf
);
vfree
(
vol
->
upd_buf
);
}
else
if
(
vol
->
changing_leb
)
{
dbg_msg
(
"only %lld of %lld bytes received for atomic LEB change"
" for volume %d:%d, cancel"
,
vol
->
upd_received
,
vol
->
upd_bytes
,
vol
->
ubi
->
ubi_num
,
vol
->
vol_id
);
vol
->
changing_leb
=
0
;
vfree
(
vol
->
upd_buf
);
}
}
ubi_close_volume
(
desc
);
ubi_close_volume
(
desc
);
...
@@ -351,24 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
...
@@ -351,24 +358,32 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
struct
ubi_volume
*
vol
=
desc
->
vol
;
struct
ubi_volume
*
vol
=
desc
->
vol
;
struct
ubi_device
*
ubi
=
vol
->
ubi
;
struct
ubi_device
*
ubi
=
vol
->
ubi
;
if
(
!
vol
->
updating
)
if
(
!
vol
->
updating
&&
!
vol
->
changing_leb
)
return
vol_cdev_direct_write
(
file
,
buf
,
count
,
offp
);
return
vol_cdev_direct_write
(
file
,
buf
,
count
,
offp
);
if
(
vol
->
updating
)
err
=
ubi_more_update_data
(
ubi
,
vol
,
buf
,
count
);
err
=
ubi_more_update_data
(
ubi
,
vol
,
buf
,
count
);
else
err
=
ubi_more_leb_change_data
(
ubi
,
vol
,
buf
,
count
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
ubi_err
(
"cannot
write %zd bytes of update
data, error %d"
,
ubi_err
(
"cannot
accept more %zd bytes of
data, error %d"
,
count
,
err
);
count
,
err
);
return
err
;
return
err
;
}
}
if
(
err
)
{
if
(
err
)
{
/*
/*
*
Update is finished, @err contains number of actually written
*
The operation is finished, @err contains number of actually
*
bytes now
.
*
written bytes
.
*/
*/
count
=
err
;
count
=
err
;
vol
->
updating
=
0
;
if
(
vol
->
changing_leb
)
{
revoke_exclusive
(
desc
,
UBI_READWRITE
);
return
count
;
}
err
=
ubi_check_volume
(
ubi
,
vol
->
vol_id
);
err
=
ubi_check_volume
(
ubi
,
vol
->
vol_id
);
if
(
err
<
0
)
if
(
err
<
0
)
return
err
;
return
err
;
...
@@ -433,6 +448,43 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
...
@@ -433,6 +448,43 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break
;
break
;
}
}
/* Atomic logical eraseblock change command */
case
UBI_IOCEBCH
:
{
struct
ubi_leb_change_req
req
;
err
=
copy_from_user
(
&
req
,
argp
,
sizeof
(
struct
ubi_leb_change_req
));
if
(
err
)
{
err
=
-
EFAULT
;
break
;
}
if
(
desc
->
mode
==
UBI_READONLY
||
vol
->
vol_type
==
UBI_STATIC_VOLUME
)
{
err
=
-
EROFS
;
break
;
}
/* Validate the request */
err
=
-
EINVAL
;
if
(
req
.
lnum
<
0
||
req
.
lnum
>=
vol
->
reserved_pebs
||
req
.
bytes
<
0
||
req
.
lnum
>=
vol
->
usable_leb_size
)
break
;
if
(
req
.
dtype
!=
UBI_LONGTERM
&&
req
.
dtype
!=
UBI_SHORTTERM
&&
req
.
dtype
!=
UBI_UNKNOWN
)
break
;
err
=
get_exclusive
(
desc
);
if
(
err
<
0
)
break
;
err
=
ubi_start_leb_change
(
ubi
,
vol
,
&
req
);
if
(
req
.
bytes
==
0
)
revoke_exclusive
(
desc
,
UBI_READWRITE
);
break
;
}
#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
/* Logical eraseblock erasure command */
/* Logical eraseblock erasure command */
case
UBI_IOCEBER
:
case
UBI_IOCEBER
:
...
@@ -445,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
...
@@ -445,7 +497,8 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break
;
break
;
}
}
if
(
desc
->
mode
==
UBI_READONLY
)
{
if
(
desc
->
mode
==
UBI_READONLY
||
vol
->
vol_type
==
UBI_STATIC_VOLUME
)
{
err
=
-
EROFS
;
err
=
-
EROFS
;
break
;
break
;
}
}
...
@@ -455,11 +508,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
...
@@ -455,11 +508,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break
;
break
;
}
}
if
(
vol
->
vol_type
!=
UBI_DYNAMIC_VOLUME
)
{
err
=
-
EROFS
;
break
;
}
dbg_msg
(
"erase LEB %d:%d"
,
vol
->
vol_id
,
lnum
);
dbg_msg
(
"erase LEB %d:%d"
,
vol
->
vol_id
,
lnum
);
err
=
ubi_eba_unmap_leb
(
ubi
,
vol
,
lnum
);
err
=
ubi_eba_unmap_leb
(
ubi
,
vol
,
lnum
);
if
(
err
)
if
(
err
)
...
...
drivers/mtd/ubi/ubi.h
浏览文件 @
e653879c
...
@@ -158,15 +158,23 @@ struct ubi_volume_desc;
...
@@ -158,15 +158,23 @@ struct ubi_volume_desc;
* @name: volume name
* @name: volume name
*
*
* @upd_ebs: how many eraseblocks are expected to be updated
* @upd_ebs: how many eraseblocks are expected to be updated
* @upd_bytes: how many bytes are expected to be received
* @ch_lnum: LEB number which is being changing by the atomic LEB change
* @upd_received: how many update bytes were already received
* operation
* @upd_buf: update buffer which is used to collect update data
* @ch_dtype: data persistency type which is being changing by the atomic LEB
* change operation
* @upd_bytes: how many bytes are expected to be received for volume update or
* atomic LEB change
* @upd_received: how many bytes were already received for volume update or
* atomic LEB change
* @upd_buf: update buffer which is used to collect update data or data for
* atomic LEB change
*
*
* @eba_tbl: EBA table of this volume (LEB->PEB mapping)
* @eba_tbl: EBA table of this volume (LEB->PEB mapping)
* @checked: %1 if this static volume was checked
* @checked: %1 if this static volume was checked
* @corrupted: %1 if the volume is corrupted (static volumes only)
* @corrupted: %1 if the volume is corrupted (static volumes only)
* @upd_marker: %1 if the update marker is set for this volume
* @upd_marker: %1 if the update marker is set for this volume
* @updating: %1 if the volume is being updated
* @updating: %1 if the volume is being updated
* @changing_leb: %1 if the atomic LEB change ioctl command is in progress
*
*
* @gluebi_desc: gluebi UBI volume descriptor
* @gluebi_desc: gluebi UBI volume descriptor
* @gluebi_refcount: reference count of the gluebi MTD device
* @gluebi_refcount: reference count of the gluebi MTD device
...
@@ -202,6 +210,8 @@ struct ubi_volume {
...
@@ -202,6 +210,8 @@ struct ubi_volume {
char
name
[
UBI_VOL_NAME_MAX
+
1
];
char
name
[
UBI_VOL_NAME_MAX
+
1
];
int
upd_ebs
;
int
upd_ebs
;
int
ch_lnum
;
int
ch_dtype
;
long
long
upd_bytes
;
long
long
upd_bytes
;
long
long
upd_received
;
long
long
upd_received
;
void
*
upd_buf
;
void
*
upd_buf
;
...
@@ -211,9 +221,14 @@ struct ubi_volume {
...
@@ -211,9 +221,14 @@ struct ubi_volume {
int
corrupted
:
1
;
int
corrupted
:
1
;
int
upd_marker
:
1
;
int
upd_marker
:
1
;
int
updating
:
1
;
int
updating
:
1
;
int
changing_leb
:
1
;
#ifdef CONFIG_MTD_UBI_GLUEBI
#ifdef CONFIG_MTD_UBI_GLUEBI
/* Gluebi-related stuff may be compiled out */
/*
* Gluebi-related stuff may be compiled out.
* TODO: this should not be built into UBI but should be a separate
* ubimtd driver which works on top of UBI and emulates MTD devices.
*/
struct
ubi_volume_desc
*
gluebi_desc
;
struct
ubi_volume_desc
*
gluebi_desc
;
int
gluebi_refcount
;
int
gluebi_refcount
;
struct
mtd_info
gluebi_mtd
;
struct
mtd_info
gluebi_mtd
;
...
@@ -427,6 +442,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
...
@@ -427,6 +442,10 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
long
long
bytes
);
long
long
bytes
);
int
ubi_more_update_data
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
int
ubi_more_update_data
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
const
void
__user
*
buf
,
int
count
);
const
void
__user
*
buf
,
int
count
);
int
ubi_start_leb_change
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
const
struct
ubi_leb_change_req
*
req
);
int
ubi_more_leb_change_data
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
const
void
__user
*
buf
,
int
count
);
/* misc.c */
/* misc.c */
int
ubi_calc_data_len
(
const
struct
ubi_device
*
ubi
,
const
void
*
buf
,
int
length
);
int
ubi_calc_data_len
(
const
struct
ubi_device
*
ubi
,
const
void
*
buf
,
int
length
);
...
...
drivers/mtd/ubi/upd.c
浏览文件 @
e653879c
...
@@ -22,7 +22,8 @@
...
@@ -22,7 +22,8 @@
*/
*/
/*
/*
* This file contains implementation of the volume update functionality.
* This file contains implementation of the volume update and atomic LEB change
* functionality.
*
*
* The update operation is based on the per-volume update marker which is
* The update operation is based on the per-volume update marker which is
* stored in the volume table. The update marker is set before the update
* stored in the volume table. The update marker is set before the update
...
@@ -133,6 +134,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
...
@@ -133,6 +134,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
uint64_t
tmp
;
uint64_t
tmp
;
dbg_msg
(
"start update of volume %d, %llu bytes"
,
vol
->
vol_id
,
bytes
);
dbg_msg
(
"start update of volume %d, %llu bytes"
,
vol
->
vol_id
,
bytes
);
ubi_assert
(
!
vol
->
updating
&&
!
vol
->
changing_leb
);
vol
->
updating
=
1
;
vol
->
updating
=
1
;
err
=
set_update_marker
(
ubi
,
vol
);
err
=
set_update_marker
(
ubi
,
vol
);
...
@@ -167,6 +169,39 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
...
@@ -167,6 +169,39 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
return
0
;
return
0
;
}
}
/**
* ubi_start_leb_change - start atomic LEB change.
* @ubi: UBI device description object
* @vol: volume description object
* @req: operation request
*
* This function starts atomic LEB change operation. Returns zero in case of
* success and a negative error code in case of failure.
*/
int
ubi_start_leb_change
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
const
struct
ubi_leb_change_req
*
req
)
{
ubi_assert
(
!
vol
->
updating
&&
!
vol
->
changing_leb
);
dbg_msg
(
"start changing LEB %d:%d, %u bytes"
,
vol
->
vol_id
,
req
->
lnum
,
req
->
bytes
);
if
(
req
->
bytes
==
0
)
return
ubi_eba_atomic_leb_change
(
ubi
,
vol
,
req
->
lnum
,
NULL
,
0
,
req
->
dtype
);
vol
->
upd_bytes
=
req
->
bytes
;
vol
->
upd_received
=
0
;
vol
->
changing_leb
=
1
;
vol
->
ch_lnum
=
req
->
lnum
;
vol
->
ch_dtype
=
req
->
dtype
;
vol
->
upd_buf
=
vmalloc
(
req
->
bytes
);
if
(
!
vol
->
upd_buf
)
return
-
ENOMEM
;
return
0
;
}
/**
/**
* write_leb - write update data.
* write_leb - write update data.
* @ubi: UBI device description object
* @ubi: UBI device description object
...
@@ -199,21 +234,19 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
...
@@ -199,21 +234,19 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
static
int
write_leb
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
int
lnum
,
static
int
write_leb
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
int
lnum
,
void
*
buf
,
int
len
,
int
used_ebs
)
void
*
buf
,
int
len
,
int
used_ebs
)
{
{
int
err
,
l
;
int
err
;
if
(
vol
->
vol_type
==
UBI_DYNAMIC_VOLUME
)
{
if
(
vol
->
vol_type
==
UBI_DYNAMIC_VOLUME
)
{
l
=
ALIGN
(
len
,
ubi
->
min_io_size
);
l
en
=
ALIGN
(
len
,
ubi
->
min_io_size
);
memset
(
buf
+
len
,
0xFF
,
l
-
len
);
memset
(
buf
+
len
,
0xFF
,
l
en
-
len
);
l
=
ubi_calc_data_len
(
ubi
,
buf
,
l
);
l
en
=
ubi_calc_data_len
(
ubi
,
buf
,
len
);
if
(
l
==
0
)
{
if
(
l
en
==
0
)
{
dbg_msg
(
"all %d bytes contain 0xFF - skip"
,
len
);
dbg_msg
(
"all %d bytes contain 0xFF - skip"
,
len
);
return
0
;
return
0
;
}
}
if
(
len
!=
l
)
dbg_msg
(
"skip last %d bytes (0xFF)"
,
len
-
l
);
err
=
ubi_eba_write_leb
(
ubi
,
vol
,
lnum
,
buf
,
0
,
l
,
UBI_UNKNOWN
);
err
=
ubi_eba_write_leb
(
ubi
,
vol
,
lnum
,
buf
,
0
,
l
en
,
UBI_UNKNOWN
);
}
else
{
}
else
{
/*
/*
* When writing static volume, and this is the last logical
* When writing static volume, and this is the last logical
...
@@ -239,9 +272,9 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
...
@@ -239,9 +272,9 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* @count: how much bytes to write
* @count: how much bytes to write
*
*
* This function writes more data to the volume which is being updated. It may
* This function writes more data to the volume which is being updated. It may
* be called arbitrary number of times until all
of the update data arrive.
* be called arbitrary number of times until all
the update data arriveis. This
*
This function returns %0 in case of success, number of bytes written during
*
function returns %0 in case of success, number of bytes written during the
*
the last call if the whole volume update was
successfully finished, and a
*
last call if the whole volume update has been
successfully finished, and a
* negative error code in case of failure.
* negative error code in case of failure.
*/
*/
int
ubi_more_update_data
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
int
ubi_more_update_data
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
...
@@ -340,6 +373,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
...
@@ -340,6 +373,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
return
err
;
return
err
;
err
=
ubi_wl_flush
(
ubi
);
err
=
ubi_wl_flush
(
ubi
);
if
(
err
==
0
)
{
if
(
err
==
0
)
{
vol
->
updating
=
0
;
err
=
to_write
;
err
=
to_write
;
vfree
(
vol
->
upd_buf
);
vfree
(
vol
->
upd_buf
);
}
}
...
@@ -347,3 +381,57 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
...
@@ -347,3 +381,57 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
return
err
;
return
err
;
}
}
/**
* ubi_more_leb_change_data - accept more data for atomic LEB change.
* @vol: volume description object
* @buf: write data (user-space memory buffer)
* @count: how much bytes to write
*
* This function accepts more data to the volume which is being under the
* "atomic LEB change" operation. It may be called arbitrary number of times
* until all data arrives. This function returns %0 in case of success, number
* of bytes written during the last call if the whole "atomic LEB change"
* operation has been successfully finished, and a negative error code in case
* of failure.
*/
int
ubi_more_leb_change_data
(
struct
ubi_device
*
ubi
,
struct
ubi_volume
*
vol
,
const
void
__user
*
buf
,
int
count
)
{
int
err
;
dbg_msg
(
"write %d of %lld bytes, %lld already passed"
,
count
,
vol
->
upd_bytes
,
vol
->
upd_received
);
if
(
ubi
->
ro_mode
)
return
-
EROFS
;
if
(
vol
->
upd_received
+
count
>
vol
->
upd_bytes
)
count
=
vol
->
upd_bytes
-
vol
->
upd_received
;
err
=
copy_from_user
(
vol
->
upd_buf
+
vol
->
upd_received
,
buf
,
count
);
if
(
err
)
return
-
EFAULT
;
vol
->
upd_received
+=
count
;
if
(
vol
->
upd_received
==
vol
->
upd_bytes
)
{
int
len
=
ALIGN
((
int
)
vol
->
upd_bytes
,
ubi
->
min_io_size
);
memset
(
vol
->
upd_buf
+
vol
->
upd_bytes
,
0xFF
,
len
-
vol
->
upd_bytes
);
len
=
ubi_calc_data_len
(
ubi
,
vol
->
upd_buf
,
len
);
err
=
ubi_eba_atomic_leb_change
(
ubi
,
vol
,
vol
->
ch_lnum
,
vol
->
upd_buf
,
len
,
UBI_UNKNOWN
);
if
(
err
)
return
err
;
}
ubi_assert
(
vol
->
upd_received
<=
vol
->
upd_bytes
);
if
(
vol
->
upd_received
==
vol
->
upd_bytes
)
{
vol
->
changing_leb
=
0
;
err
=
count
;
vfree
(
vol
->
upd_buf
);
}
return
err
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录