Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
51c3509e
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看板
提交
51c3509e
编写于
1月 29, 2018
作者:
I
Ilya Dryomov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rbd: remove old request handling code
Signed-off-by:
N
Ilya Dryomov
<
idryomov@gmail.com
>
上级
3da691bf
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
4 addition
and
730 deletion
+4
-730
drivers/block/rbd.c
drivers/block/rbd.c
+4
-730
未找到文件。
drivers/block/rbd.c
浏览文件 @
51c3509e
...
@@ -231,8 +231,6 @@ enum obj_operation_type {
...
@@ -231,8 +231,6 @@ enum obj_operation_type {
enum
obj_req_flags
{
enum
obj_req_flags
{
OBJ_REQ_DONE
,
/* completion flag: not done = 0, done = 1 */
OBJ_REQ_DONE
,
/* completion flag: not done = 0, done = 1 */
OBJ_REQ_IMG_DATA
,
/* object usage: standalone = 0, image = 1 */
OBJ_REQ_IMG_DATA
,
/* object usage: standalone = 0, image = 1 */
OBJ_REQ_KNOWN
,
/* EXISTS flag valid: no = 0, yes = 1 */
OBJ_REQ_EXISTS
,
/* target exists: no = 0, yes = 1 */
};
};
/*
/*
...
@@ -271,27 +269,15 @@ struct rbd_obj_request {
...
@@ -271,27 +269,15 @@ struct rbd_obj_request {
* An object request associated with an image will have its
* An object request associated with an image will have its
* img_data flag set; a standalone object request will not.
* img_data flag set; a standalone object request will not.
*
*
* A standalone object request will have which == BAD_WHICH
* and a null obj_request pointer.
*
* An object request initiated in support of a layered image
* object (to check for its existence before a write) will
* have which == BAD_WHICH and a non-null obj_request pointer.
*
* Finally, an object request for rbd image data will have
* Finally, an object request for rbd image data will have
* which != BAD_WHICH, and will have a non-null img_request
* which != BAD_WHICH, and will have a non-null img_request
* pointer. The value of which will be in the range
* pointer. The value of which will be in the range
* 0..(img_request->obj_request_count-1).
* 0..(img_request->obj_request_count-1).
*/
*/
union
{
struct
rbd_obj_request
*
obj_request
;
/* STAT op */
struct
{
struct
rbd_img_request
*
img_request
;
struct
rbd_img_request
*
img_request
;
u64
img_offset
;
u64
img_offset
;
/* links for img_request->obj_requests list */
/* links for img_request->obj_requests list */
struct
list_head
links
;
struct
list_head
links
;
};
};
u32
which
;
/* posn image request list */
u32
which
;
/* posn image request list */
enum
obj_request_type
type
;
enum
obj_request_type
type
;
...
@@ -480,8 +466,6 @@ static bool single_major = true;
...
@@ -480,8 +466,6 @@ static bool single_major = true;
module_param
(
single_major
,
bool
,
S_IRUGO
);
module_param
(
single_major
,
bool
,
S_IRUGO
);
MODULE_PARM_DESC
(
single_major
,
"Use a single major number for all rbd devices (default: true)"
);
MODULE_PARM_DESC
(
single_major
,
"Use a single major number for all rbd devices (default: true)"
);
static
int
rbd_img_request_submit
(
struct
rbd_img_request
*
img_request
);
static
ssize_t
rbd_add
(
struct
bus_type
*
bus
,
const
char
*
buf
,
static
ssize_t
rbd_add
(
struct
bus_type
*
bus
,
const
char
*
buf
,
size_t
count
);
size_t
count
);
static
ssize_t
rbd_remove
(
struct
bus_type
*
bus
,
const
char
*
buf
,
static
ssize_t
rbd_remove
(
struct
bus_type
*
bus
,
const
char
*
buf
,
...
@@ -610,9 +594,6 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
...
@@ -610,9 +594,6 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
# define rbd_assert(expr) ((void) 0)
# define rbd_assert(expr) ((void) 0)
#endif
/* !RBD_DEBUG */
#endif
/* !RBD_DEBUG */
static
void
rbd_osd_copyup_callback
(
struct
rbd_obj_request
*
obj_request
);
static
int
rbd_img_obj_request_submit
(
struct
rbd_obj_request
*
obj_request
);
static
void
rbd_img_parent_read
(
struct
rbd_obj_request
*
obj_request
);
static
void
rbd_dev_remove_parent
(
struct
rbd_device
*
rbd_dev
);
static
void
rbd_dev_remove_parent
(
struct
rbd_device
*
rbd_dev
);
static
int
rbd_dev_refresh
(
struct
rbd_device
*
rbd_dev
);
static
int
rbd_dev_refresh
(
struct
rbd_device
*
rbd_dev
);
...
@@ -1369,37 +1350,6 @@ static bool obj_request_done_test(struct rbd_obj_request *obj_request)
...
@@ -1369,37 +1350,6 @@ static bool obj_request_done_test(struct rbd_obj_request *obj_request)
return
test_bit
(
OBJ_REQ_DONE
,
&
obj_request
->
flags
)
!=
0
;
return
test_bit
(
OBJ_REQ_DONE
,
&
obj_request
->
flags
)
!=
0
;
}
}
/*
* This sets the KNOWN flag after (possibly) setting the EXISTS
* flag. The latter is set based on the "exists" value provided.
*
* Note that for our purposes once an object exists it never goes
* away again. It's possible that the response from two existence
* checks are separated by the creation of the target object, and
* the first ("doesn't exist") response arrives *after* the second
* ("does exist"). In that case we ignore the second one.
*/
static
void
obj_request_existence_set
(
struct
rbd_obj_request
*
obj_request
,
bool
exists
)
{
if
(
exists
)
set_bit
(
OBJ_REQ_EXISTS
,
&
obj_request
->
flags
);
set_bit
(
OBJ_REQ_KNOWN
,
&
obj_request
->
flags
);
smp_mb
();
}
static
bool
obj_request_known_test
(
struct
rbd_obj_request
*
obj_request
)
{
smp_mb
();
return
test_bit
(
OBJ_REQ_KNOWN
,
&
obj_request
->
flags
)
!=
0
;
}
static
bool
obj_request_exists_test
(
struct
rbd_obj_request
*
obj_request
)
{
smp_mb
();
return
test_bit
(
OBJ_REQ_EXISTS
,
&
obj_request
->
flags
)
!=
0
;
}
static
bool
obj_request_overlaps_parent
(
struct
rbd_obj_request
*
obj_request
)
static
bool
obj_request_overlaps_parent
(
struct
rbd_obj_request
*
obj_request
)
{
{
struct
rbd_device
*
rbd_dev
=
obj_request
->
img_request
->
rbd_dev
;
struct
rbd_device
*
rbd_dev
=
obj_request
->
img_request
->
rbd_dev
;
...
@@ -1643,42 +1593,6 @@ static bool rbd_img_is_write(struct rbd_img_request *img_req)
...
@@ -1643,42 +1593,6 @@ static bool rbd_img_is_write(struct rbd_img_request *img_req)
}
}
}
}
static
void
rbd_img_obj_request_read_callback
(
struct
rbd_obj_request
*
obj_request
)
{
u64
xferred
=
obj_request
->
xferred
;
u64
length
=
obj_request
->
length
;
dout
(
"%s: obj %p img %p result %d %llu/%llu
\n
"
,
__func__
,
obj_request
,
obj_request
->
img_request
,
obj_request
->
result
,
xferred
,
length
);
/*
* ENOENT means a hole in the image. We zero-fill the entire
* length of the request. A short read also implies zero-fill
* to the end of the request. An error requires the whole
* length of the request to be reported finished with an error
* to the block layer. In each case we update the xferred
* count to indicate the whole request was satisfied.
*/
rbd_assert
(
obj_request
->
type
!=
OBJ_REQUEST_NODATA
);
if
(
obj_request
->
result
==
-
ENOENT
)
{
if
(
obj_request
->
type
==
OBJ_REQUEST_BIO
)
zero_bios
(
&
obj_request
->
bio_pos
,
0
,
length
);
else
zero_bvecs
(
&
obj_request
->
bvec_pos
,
0
,
length
);
obj_request
->
result
=
0
;
}
else
if
(
xferred
<
length
&&
!
obj_request
->
result
)
{
if
(
obj_request
->
type
==
OBJ_REQUEST_BIO
)
zero_bios
(
&
obj_request
->
bio_pos
,
xferred
,
length
-
xferred
);
else
zero_bvecs
(
&
obj_request
->
bvec_pos
,
xferred
,
length
-
xferred
);
}
obj_request
->
xferred
=
length
;
obj_request_done_set
(
obj_request
);
}
static
void
rbd_obj_request_complete
(
struct
rbd_obj_request
*
obj_request
)
static
void
rbd_obj_request_complete
(
struct
rbd_obj_request
*
obj_request
)
{
{
dout
(
"%s: obj %p cb %p
\n
"
,
__func__
,
obj_request
,
dout
(
"%s: obj %p cb %p
\n
"
,
__func__
,
obj_request
,
...
@@ -1686,93 +1600,6 @@ static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
...
@@ -1686,93 +1600,6 @@ static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
obj_request
->
callback
(
obj_request
);
obj_request
->
callback
(
obj_request
);
}
}
static
void
rbd_obj_request_error
(
struct
rbd_obj_request
*
obj_request
,
int
err
)
{
obj_request
->
result
=
err
;
obj_request
->
xferred
=
0
;
/*
* kludge - mirror rbd_obj_request_submit() to match a put in
* rbd_img_obj_callback()
*/
if
(
obj_request_img_data_test
(
obj_request
))
{
WARN_ON
(
obj_request
->
callback
!=
rbd_img_obj_callback
);
rbd_img_request_get
(
obj_request
->
img_request
);
}
obj_request_done_set
(
obj_request
);
rbd_obj_request_complete
(
obj_request
);
}
static
void
rbd_osd_read_callback
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_img_request
*
img_request
=
NULL
;
struct
rbd_device
*
rbd_dev
=
NULL
;
bool
layered
=
false
;
if
(
obj_request_img_data_test
(
obj_request
))
{
img_request
=
obj_request
->
img_request
;
layered
=
img_request
&&
img_request_layered_test
(
img_request
);
rbd_dev
=
img_request
->
rbd_dev
;
}
dout
(
"%s: obj %p img %p result %d %llu/%llu
\n
"
,
__func__
,
obj_request
,
img_request
,
obj_request
->
result
,
obj_request
->
xferred
,
obj_request
->
length
);
if
(
layered
&&
obj_request
->
result
==
-
ENOENT
&&
obj_request
->
img_offset
<
rbd_dev
->
parent_overlap
)
rbd_img_parent_read
(
obj_request
);
else
if
(
img_request
)
rbd_img_obj_request_read_callback
(
obj_request
);
else
obj_request_done_set
(
obj_request
);
}
static
void
rbd_osd_write_callback
(
struct
rbd_obj_request
*
obj_request
)
{
dout
(
"%s: obj %p result %d %llu
\n
"
,
__func__
,
obj_request
,
obj_request
->
result
,
obj_request
->
length
);
/*
* There is no such thing as a successful short write. Set
* it to our originally-requested length.
*/
obj_request
->
xferred
=
obj_request
->
length
;
obj_request_done_set
(
obj_request
);
}
static
void
rbd_osd_discard_callback
(
struct
rbd_obj_request
*
obj_request
)
{
dout
(
"%s: obj %p result %d %llu
\n
"
,
__func__
,
obj_request
,
obj_request
->
result
,
obj_request
->
length
);
/*
* There is no such thing as a successful short discard. Set
* it to our originally-requested length.
*/
obj_request
->
xferred
=
obj_request
->
length
;
/* discarding a non-existent object is not a problem */
if
(
obj_request
->
result
==
-
ENOENT
)
obj_request
->
result
=
0
;
obj_request_done_set
(
obj_request
);
}
/*
* For a simple stat call there's nothing to do. We'll do more if
* this is part of a write sequence for a layered image.
*/
static
void
rbd_osd_stat_callback
(
struct
rbd_obj_request
*
obj_request
)
{
dout
(
"%s: obj %p
\n
"
,
__func__
,
obj_request
);
obj_request_done_set
(
obj_request
);
}
static
void
rbd_osd_call_callback
(
struct
rbd_obj_request
*
obj_request
)
{
dout
(
"%s: obj %p
\n
"
,
__func__
,
obj_request
);
if
(
obj_request_img_data_test
(
obj_request
))
rbd_osd_copyup_callback
(
obj_request
);
else
obj_request_done_set
(
obj_request
);
}
static
void
rbd_obj_handle_request
(
struct
rbd_obj_request
*
obj_req
);
static
void
rbd_obj_handle_request
(
struct
rbd_obj_request
*
obj_req
);
static
void
rbd_osd_req_callback
(
struct
ceph_osd_request
*
osd_req
)
static
void
rbd_osd_req_callback
(
struct
ceph_osd_request
*
osd_req
)
...
@@ -1871,32 +1698,6 @@ static struct ceph_osd_request *rbd_osd_req_create(
...
@@ -1871,32 +1698,6 @@ static struct ceph_osd_request *rbd_osd_req_create(
CEPH_OSD_FLAG_WRITE
:
CEPH_OSD_FLAG_READ
,
obj_request
);
CEPH_OSD_FLAG_WRITE
:
CEPH_OSD_FLAG_READ
,
obj_request
);
}
}
/*
* Create a copyup osd request based on the information in the object
* request supplied. A copyup request has two or three osd ops, a
* copyup method call, potentially a hint op, and a write or truncate
* or zero op.
*/
static
struct
ceph_osd_request
*
rbd_osd_req_create_copyup
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_img_request
*
img_request
;
int
num_osd_ops
=
3
;
rbd_assert
(
obj_request_img_data_test
(
obj_request
));
img_request
=
obj_request
->
img_request
;
rbd_assert
(
img_request
);
rbd_assert
(
img_request_write_test
(
img_request
)
||
img_request_discard_test
(
img_request
));
if
(
img_request_discard_test
(
img_request
))
num_osd_ops
=
2
;
return
__rbd_osd_req_create
(
img_request
->
rbd_dev
,
img_request
->
snapc
,
num_osd_ops
,
CEPH_OSD_FLAG_WRITE
,
obj_request
);
}
static
void
rbd_osd_req_destroy
(
struct
ceph_osd_request
*
osd_req
)
static
void
rbd_osd_req_destroy
(
struct
ceph_osd_request
*
osd_req
)
{
{
ceph_osdc_put_request
(
osd_req
);
ceph_osdc_put_request
(
osd_req
);
...
@@ -2217,73 +2018,6 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_request)
...
@@ -2217,73 +2018,6 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_request)
rbd_img_request_complete
(
img_request
);
rbd_img_request_complete
(
img_request
);
}
}
/*
* Add individual osd ops to the given ceph_osd_request and prepare
* them for submission. num_ops is the current number of
* osd operations already to the object request.
*/
static
void
rbd_img_obj_request_fill
(
struct
rbd_obj_request
*
obj_request
,
struct
ceph_osd_request
*
osd_request
,
enum
obj_operation_type
op_type
,
unsigned
int
num_ops
)
{
struct
rbd_img_request
*
img_request
=
obj_request
->
img_request
;
struct
rbd_device
*
rbd_dev
=
img_request
->
rbd_dev
;
u64
object_size
=
rbd_obj_bytes
(
&
rbd_dev
->
header
);
u64
offset
=
obj_request
->
offset
;
u64
length
=
obj_request
->
length
;
u64
img_end
;
u16
opcode
;
if
(
op_type
==
OBJ_OP_DISCARD
)
{
if
(
!
offset
&&
length
==
object_size
&&
(
!
img_request_layered_test
(
img_request
)
||
!
obj_request_overlaps_parent
(
obj_request
)))
{
opcode
=
CEPH_OSD_OP_DELETE
;
}
else
if
((
offset
+
length
==
object_size
))
{
opcode
=
CEPH_OSD_OP_TRUNCATE
;
}
else
{
down_read
(
&
rbd_dev
->
header_rwsem
);
img_end
=
rbd_dev
->
header
.
image_size
;
up_read
(
&
rbd_dev
->
header_rwsem
);
if
(
obj_request
->
img_offset
+
length
==
img_end
)
opcode
=
CEPH_OSD_OP_TRUNCATE
;
else
opcode
=
CEPH_OSD_OP_ZERO
;
}
}
else
if
(
op_type
==
OBJ_OP_WRITE
)
{
if
(
!
offset
&&
length
==
object_size
)
opcode
=
CEPH_OSD_OP_WRITEFULL
;
else
opcode
=
CEPH_OSD_OP_WRITE
;
osd_req_op_alloc_hint_init
(
osd_request
,
num_ops
,
object_size
,
object_size
);
num_ops
++
;
}
else
{
opcode
=
CEPH_OSD_OP_READ
;
}
if
(
opcode
==
CEPH_OSD_OP_DELETE
)
osd_req_op_init
(
osd_request
,
num_ops
,
opcode
,
0
);
else
osd_req_op_extent_init
(
osd_request
,
num_ops
,
opcode
,
offset
,
length
,
0
,
0
);
if
(
obj_request
->
type
==
OBJ_REQUEST_BIO
)
osd_req_op_extent_osd_data_bio
(
osd_request
,
num_ops
,
&
obj_request
->
bio_pos
,
length
);
else
if
(
obj_request
->
type
==
OBJ_REQUEST_BVECS
)
osd_req_op_extent_osd_data_bvec_pos
(
osd_request
,
num_ops
,
&
obj_request
->
bvec_pos
);
/* Discards are also writes */
if
(
op_type
==
OBJ_OP_WRITE
||
op_type
==
OBJ_OP_DISCARD
)
rbd_osd_req_format_write
(
obj_request
);
else
rbd_osd_req_format_read
(
obj_request
);
}
static
void
rbd_osd_req_setup_data
(
struct
rbd_obj_request
*
obj_req
,
u32
which
)
static
void
rbd_osd_req_setup_data
(
struct
rbd_obj_request
*
obj_req
,
u32
which
)
{
{
switch
(
obj_req
->
type
)
{
switch
(
obj_req
->
type
)
{
...
@@ -2568,366 +2302,6 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
...
@@ -2568,366 +2302,6 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
static
void
rbd_osd_copyup_callback
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_img_request
*
img_request
;
struct
rbd_device
*
rbd_dev
;
dout
(
"%s: obj %p
\n
"
,
__func__
,
obj_request
);
rbd_assert
(
obj_request
->
type
==
OBJ_REQUEST_BIO
||
obj_request
->
type
==
OBJ_REQUEST_NODATA
);
rbd_assert
(
obj_request_img_data_test
(
obj_request
));
img_request
=
obj_request
->
img_request
;
rbd_assert
(
img_request
);
rbd_dev
=
img_request
->
rbd_dev
;
rbd_assert
(
rbd_dev
);
/*
* We want the transfer count to reflect the size of the
* original write request. There is no such thing as a
* successful short write, so if the request was successful
* we can just set it to the originally-requested length.
*/
if
(
!
obj_request
->
result
)
obj_request
->
xferred
=
obj_request
->
length
;
obj_request_done_set
(
obj_request
);
}
static
void
rbd_img_obj_parent_read_full_callback
(
struct
rbd_img_request
*
img_request
)
{
struct
rbd_obj_request
*
orig_request
;
struct
ceph_osd_request
*
osd_req
;
struct
rbd_device
*
rbd_dev
;
enum
obj_operation_type
op_type
;
int
img_result
;
u64
parent_length
;
rbd_assert
(
img_request_child_test
(
img_request
));
/* First get what we need from the image request */
orig_request
=
img_request
->
obj_request
;
rbd_assert
(
orig_request
!=
NULL
);
rbd_assert
(
obj_request_type_valid
(
orig_request
->
type
));
img_result
=
img_request
->
result
;
parent_length
=
img_request
->
length
;
rbd_assert
(
img_result
||
parent_length
==
img_request
->
xferred
);
rbd_img_request_put
(
img_request
);
rbd_assert
(
orig_request
->
img_request
);
rbd_dev
=
orig_request
->
img_request
->
rbd_dev
;
rbd_assert
(
rbd_dev
);
/*
* If the overlap has become 0 (most likely because the
* image has been flattened) we need to free the pages
* and re-submit the original write request.
*/
if
(
!
rbd_dev
->
parent_overlap
)
{
rbd_obj_request_submit
(
orig_request
);
return
;
}
if
(
img_result
)
goto
out_err
;
/*
* The original osd request is of no use to use any more.
* We need a new one that can hold the three ops in a copyup
* request. Allocate the new copyup osd request for the
* original request, and release the old one.
*/
img_result
=
-
ENOMEM
;
osd_req
=
rbd_osd_req_create_copyup
(
orig_request
);
if
(
!
osd_req
)
goto
out_err
;
rbd_osd_req_destroy
(
orig_request
->
osd_req
);
orig_request
->
osd_req
=
osd_req
;
/* Initialize the copyup op */
osd_req_op_cls_init
(
osd_req
,
0
,
CEPH_OSD_OP_CALL
,
"rbd"
,
"copyup"
);
osd_req_op_cls_request_data_bvecs
(
osd_req
,
0
,
orig_request
->
copyup_bvecs
,
parent_length
);
/* Add the other op(s) */
op_type
=
rbd_img_request_op_type
(
orig_request
->
img_request
);
rbd_img_obj_request_fill
(
orig_request
,
osd_req
,
op_type
,
1
);
/* All set, send it off. */
rbd_obj_request_submit
(
orig_request
);
return
;
out_err:
rbd_obj_request_error
(
orig_request
,
img_result
);
}
static
int
setup_copyup_bvecs
(
struct
rbd_obj_request
*
obj_req
,
u64
obj_overlap
);
/*
* Read from the parent image the range of data that covers the
* entire target of the given object request. This is used for
* satisfying a layered image write request when the target of an
* object request from the image request does not exist.
*
* A page array big enough to hold the returned data is allocated
* and supplied to rbd_img_request_fill() as the "data descriptor."
* When the read completes, this page array will be transferred to
* the original object request for the copyup operation.
*
* If an error occurs, it is recorded as the result of the original
* object request in rbd_img_obj_exists_callback().
*/
static
int
rbd_img_obj_parent_read_full
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_device
*
rbd_dev
=
obj_request
->
img_request
->
rbd_dev
;
struct
rbd_img_request
*
parent_request
=
NULL
;
struct
ceph_bvec_iter
bvec_it
=
{
0
};
u64
img_offset
;
u64
length
;
int
result
;
rbd_assert
(
rbd_dev
->
parent
!=
NULL
);
/*
* Determine the byte range covered by the object in the
* child image to which the original request was to be sent.
*/
img_offset
=
obj_request
->
img_offset
-
obj_request
->
offset
;
length
=
rbd_obj_bytes
(
&
rbd_dev
->
header
);
/*
* There is no defined parent data beyond the parent
* overlap, so limit what we read at that boundary if
* necessary.
*/
if
(
img_offset
+
length
>
rbd_dev
->
parent_overlap
)
{
rbd_assert
(
img_offset
<
rbd_dev
->
parent_overlap
);
length
=
rbd_dev
->
parent_overlap
-
img_offset
;
}
/*
* Allocate a page array big enough to receive the data read
* from the parent.
*/
result
=
setup_copyup_bvecs
(
obj_request
,
length
);
if
(
result
)
goto
out_err
;
result
=
-
ENOMEM
;
parent_request
=
rbd_parent_request_create
(
obj_request
,
img_offset
,
length
);
if
(
!
parent_request
)
goto
out_err
;
bvec_it
.
bvecs
=
obj_request
->
copyup_bvecs
;
bvec_it
.
iter
.
bi_size
=
length
;
result
=
rbd_img_request_fill
(
parent_request
,
OBJ_REQUEST_BVECS
,
&
bvec_it
);
if
(
result
)
goto
out_err
;
parent_request
->
callback
=
rbd_img_obj_parent_read_full_callback
;
result
=
rbd_img_request_submit
(
parent_request
);
if
(
!
result
)
return
0
;
out_err:
if
(
parent_request
)
rbd_img_request_put
(
parent_request
);
return
result
;
}
static
void
rbd_img_obj_exists_callback
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_obj_request
*
orig_request
;
struct
rbd_device
*
rbd_dev
;
int
result
;
rbd_assert
(
!
obj_request_img_data_test
(
obj_request
));
/*
* All we need from the object request is the original
* request and the result of the STAT op. Grab those, then
* we're done with the request.
*/
orig_request
=
obj_request
->
obj_request
;
obj_request
->
obj_request
=
NULL
;
rbd_obj_request_put
(
orig_request
);
rbd_assert
(
orig_request
);
rbd_assert
(
orig_request
->
img_request
);
result
=
obj_request
->
result
;
obj_request
->
result
=
0
;
dout
(
"%s: obj %p for obj %p result %d %llu/%llu
\n
"
,
__func__
,
obj_request
,
orig_request
,
result
,
obj_request
->
xferred
,
obj_request
->
length
);
rbd_obj_request_put
(
obj_request
);
/*
* If the overlap has become 0 (most likely because the
* image has been flattened) we need to re-submit the
* original request.
*/
rbd_dev
=
orig_request
->
img_request
->
rbd_dev
;
if
(
!
rbd_dev
->
parent_overlap
)
{
rbd_obj_request_submit
(
orig_request
);
return
;
}
/*
* Our only purpose here is to determine whether the object
* exists, and we don't want to treat the non-existence as
* an error. If something else comes back, transfer the
* error to the original request and complete it now.
*/
if
(
!
result
)
{
obj_request_existence_set
(
orig_request
,
true
);
}
else
if
(
result
==
-
ENOENT
)
{
obj_request_existence_set
(
orig_request
,
false
);
}
else
{
goto
fail_orig_request
;
}
/*
* Resubmit the original request now that we have recorded
* whether the target object exists.
*/
result
=
rbd_img_obj_request_submit
(
orig_request
);
if
(
result
)
goto
fail_orig_request
;
return
;
fail_orig_request:
rbd_obj_request_error
(
orig_request
,
result
);
}
static
int
rbd_img_obj_exists_submit
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_device
*
rbd_dev
=
obj_request
->
img_request
->
rbd_dev
;
struct
rbd_obj_request
*
stat_request
;
struct
page
**
pages
;
int
ret
;
stat_request
=
rbd_obj_request_create
(
OBJ_REQUEST_NODATA
);
if
(
!
stat_request
)
return
-
ENOMEM
;
stat_request
->
object_no
=
obj_request
->
object_no
;
stat_request
->
osd_req
=
rbd_osd_req_create
(
rbd_dev
,
OBJ_OP_READ
,
1
,
stat_request
);
if
(
!
stat_request
->
osd_req
)
{
ret
=
-
ENOMEM
;
goto
fail_stat_request
;
}
/*
* The response data for a STAT call consists of:
* le64 length;
* struct {
* le32 tv_sec;
* le32 tv_nsec;
* } mtime;
*/
pages
=
ceph_alloc_page_vector
(
1
,
GFP_NOIO
);
if
(
IS_ERR
(
pages
))
{
ret
=
PTR_ERR
(
pages
);
goto
fail_stat_request
;
}
osd_req_op_init
(
stat_request
->
osd_req
,
0
,
CEPH_OSD_OP_STAT
,
0
);
osd_req_op_raw_data_in_pages
(
stat_request
->
osd_req
,
0
,
pages
,
8
+
sizeof
(
struct
ceph_timespec
),
0
,
false
,
true
);
rbd_obj_request_get
(
obj_request
);
stat_request
->
obj_request
=
obj_request
;
stat_request
->
callback
=
rbd_img_obj_exists_callback
;
rbd_obj_request_submit
(
stat_request
);
return
0
;
fail_stat_request:
rbd_obj_request_put
(
stat_request
);
return
ret
;
}
static
bool
img_obj_request_simple
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_img_request
*
img_request
=
obj_request
->
img_request
;
struct
rbd_device
*
rbd_dev
=
img_request
->
rbd_dev
;
/* Reads */
if
(
!
img_request_write_test
(
img_request
)
&&
!
img_request_discard_test
(
img_request
))
return
true
;
/* Non-layered writes */
if
(
!
img_request_layered_test
(
img_request
))
return
true
;
/*
* Layered writes outside of the parent overlap range don't
* share any data with the parent.
*/
if
(
!
obj_request_overlaps_parent
(
obj_request
))
return
true
;
/*
* Entire-object layered writes - we will overwrite whatever
* parent data there is anyway.
*/
if
(
!
obj_request
->
offset
&&
obj_request
->
length
==
rbd_obj_bytes
(
&
rbd_dev
->
header
))
return
true
;
/*
* If the object is known to already exist, its parent data has
* already been copied.
*/
if
(
obj_request_known_test
(
obj_request
)
&&
obj_request_exists_test
(
obj_request
))
return
true
;
return
false
;
}
static
int
rbd_img_obj_request_submit
(
struct
rbd_obj_request
*
obj_request
)
{
rbd_assert
(
obj_request_img_data_test
(
obj_request
));
rbd_assert
(
obj_request_type_valid
(
obj_request
->
type
));
rbd_assert
(
obj_request
->
img_request
);
if
(
img_obj_request_simple
(
obj_request
))
{
rbd_obj_request_submit
(
obj_request
);
return
0
;
}
/*
* It's a layered write. The target object might exist but
* we may not know that yet. If we know it doesn't exist,
* start by reading the data for the full target object from
* the parent so we can use it for a copyup to the target.
*/
if
(
obj_request_known_test
(
obj_request
))
return
rbd_img_obj_parent_read_full
(
obj_request
);
/* We don't know whether the target exists. Go find out. */
return
rbd_img_obj_exists_submit
(
obj_request
);
}
static
int
rbd_img_request_submit
(
struct
rbd_img_request
*
img_request
)
static
int
rbd_img_request_submit
(
struct
rbd_img_request
*
img_request
)
{
{
struct
rbd_obj_request
*
obj_request
;
struct
rbd_obj_request
*
obj_request
;
...
@@ -3131,106 +2505,6 @@ static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
...
@@ -3131,106 +2505,6 @@ static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
return
0
;
return
0
;
}
}
static
void
rbd_img_parent_read_callback
(
struct
rbd_img_request
*
img_request
)
{
struct
rbd_obj_request
*
obj_request
;
struct
rbd_device
*
rbd_dev
;
u64
obj_end
;
u64
img_xferred
;
int
img_result
;
rbd_assert
(
img_request_child_test
(
img_request
));
/* First get what we need from the image request and release it */
obj_request
=
img_request
->
obj_request
;
img_xferred
=
img_request
->
xferred
;
img_result
=
img_request
->
result
;
rbd_img_request_put
(
img_request
);
/*
* If the overlap has become 0 (most likely because the
* image has been flattened) we need to re-submit the
* original request.
*/
rbd_assert
(
obj_request
);
rbd_assert
(
obj_request
->
img_request
);
rbd_dev
=
obj_request
->
img_request
->
rbd_dev
;
if
(
!
rbd_dev
->
parent_overlap
)
{
rbd_obj_request_submit
(
obj_request
);
return
;
}
obj_request
->
result
=
img_result
;
if
(
obj_request
->
result
)
goto
out
;
/*
* We need to zero anything beyond the parent overlap
* boundary. Since rbd_img_obj_request_read_callback()
* will zero anything beyond the end of a short read, an
* easy way to do this is to pretend the data from the
* parent came up short--ending at the overlap boundary.
*/
rbd_assert
(
obj_request
->
img_offset
<
U64_MAX
-
obj_request
->
length
);
obj_end
=
obj_request
->
img_offset
+
obj_request
->
length
;
if
(
obj_end
>
rbd_dev
->
parent_overlap
)
{
u64
xferred
=
0
;
if
(
obj_request
->
img_offset
<
rbd_dev
->
parent_overlap
)
xferred
=
rbd_dev
->
parent_overlap
-
obj_request
->
img_offset
;
obj_request
->
xferred
=
min
(
img_xferred
,
xferred
);
}
else
{
obj_request
->
xferred
=
img_xferred
;
}
out:
rbd_img_obj_request_read_callback
(
obj_request
);
rbd_obj_request_complete
(
obj_request
);
}
static
void
rbd_img_parent_read
(
struct
rbd_obj_request
*
obj_request
)
{
struct
rbd_img_request
*
img_request
;
int
result
;
rbd_assert
(
obj_request_img_data_test
(
obj_request
));
rbd_assert
(
obj_request
->
img_request
!=
NULL
);
rbd_assert
(
obj_request
->
result
==
(
s32
)
-
ENOENT
);
rbd_assert
(
obj_request_type_valid
(
obj_request
->
type
));
/* rbd_read_finish(obj_request, obj_request->length); */
img_request
=
rbd_parent_request_create
(
obj_request
,
obj_request
->
img_offset
,
obj_request
->
length
);
result
=
-
ENOMEM
;
if
(
!
img_request
)
goto
out_err
;
if
(
obj_request
->
type
==
OBJ_REQUEST_BIO
)
result
=
rbd_img_request_fill
(
img_request
,
OBJ_REQUEST_BIO
,
&
obj_request
->
bio_pos
);
else
result
=
rbd_img_request_fill
(
img_request
,
OBJ_REQUEST_BVECS
,
&
obj_request
->
bvec_pos
);
if
(
result
)
goto
out_err
;
img_request
->
callback
=
rbd_img_parent_read_callback
;
result
=
rbd_img_request_submit
(
img_request
);
if
(
result
)
goto
out_err
;
return
;
out_err:
if
(
img_request
)
rbd_img_request_put
(
img_request
);
obj_request
->
result
=
result
;
obj_request
->
xferred
=
0
;
obj_request_done_set
(
obj_request
);
}
static
int
rbd_obj_handle_write_guard
(
struct
rbd_obj_request
*
obj_req
)
static
int
rbd_obj_handle_write_guard
(
struct
rbd_obj_request
*
obj_req
)
{
{
struct
rbd_device
*
rbd_dev
=
obj_req
->
img_request
->
rbd_dev
;
struct
rbd_device
*
rbd_dev
=
obj_req
->
img_request
->
rbd_dev
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录