Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
51c3509e
Commit
51c3509e
authored
Jan 29, 2018
by
Ilya Dryomov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rbd: remove old request handling code
Signed-off-by:
Ilya Dryomov
<
idryomov@gmail.com
>
parent
3da691bf
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
4 additions
and
730 deletions
+4
-730
drivers/block/rbd.c
drivers/block/rbd.c
+4
-730
No files found.
drivers/block/rbd.c
View file @
51c3509e
...
...
@@ -231,8 +231,6 @@ enum obj_operation_type {
enum
obj_req_flags
{
OBJ_REQ_DONE
,
/* completion flag: not done = 0, done = 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 {
* An object request associated with an image will have its
* 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
* which != BAD_WHICH, and will have a non-null img_request
* pointer. The value of which will be in the range
* 0..(img_request->obj_request_count-1).
*/
union
{
struct
rbd_obj_request
*
obj_request
;
/* STAT op */
struct
{
struct
rbd_img_request
*
img_request
;
u64
img_offset
;
/* links for img_request->obj_requests list */
struct
list_head
links
;
};
};
u32
which
;
/* posn image request list */
enum
obj_request_type
type
;
...
...
@@ -480,8 +466,6 @@ static bool single_major = true;
module_param
(
single_major
,
bool
,
S_IRUGO
);
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
,
size_t
count
);
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, ...)
# define rbd_assert(expr) ((void) 0)
#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
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)
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
)
{
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)
}
}
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
)
{
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)
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_osd_req_callback
(
struct
ceph_osd_request
*
osd_req
)
...
...
@@ -1871,32 +1698,6 @@ static struct ceph_osd_request *rbd_osd_req_create(
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
)
{
ceph_osdc_put_request
(
osd_req
);
...
...
@@ -2217,73 +2018,6 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_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
)
{
switch
(
obj_req
->
type
)
{
...
...
@@ -2568,366 +2302,6 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
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
)
{
struct
rbd_obj_request
*
obj_request
;
...
...
@@ -3131,106 +2505,6 @@ static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
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
)
{
struct
rbd_device
*
rbd_dev
=
obj_req
->
img_request
->
rbd_dev
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment