diff mbox

[7/8] rbd: don't call rbd_osd_req_format_read() for !img_data requests

Message ID 1474304608-17958-8-git-send-email-idryomov@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ilya Dryomov Sept. 19, 2016, 5:03 p.m. UTC
Accessing obj_request->img_request union field is only valid for object
requests associated with an image (i.e. if obj_request_img_data_test()
returns true).  rbd_osd_req_format_read() used to do more, but now it
just sets osd_req->snap_id.  Standalone and stat object requests always
go to the HEAD revision and are fine with CEPH_NOSNAP set by libceph,
so get around the invalid union field use by simply not calling
rbd_osd_req_format_read() in those places.

Reported-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
---
 drivers/block/rbd.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

Comments

Alex Elder Sept. 25, 2016, 4:44 p.m. UTC | #1
On 09/19/2016 12:03 PM, Ilya Dryomov wrote:
> Accessing obj_request->img_request union field is only valid for object
> requests associated with an image (i.e. if obj_request_img_data_test()
> returns true).  rbd_osd_req_format_read() used to do more, but now it
> just sets osd_req->snap_id.  Standalone and stat object requests always
> go to the HEAD revision and are fine with CEPH_NOSNAP set by libceph,
> so get around the invalid union field use by simply not calling
> rbd_osd_req_format_read() in those places.

Since rbd_osd_req_format_{read,write} are now only called
from rbd_img_obj_request_fill(), and they're really simple,
maybe they could be eliminated entirely and open-coded
instead.  We already have the img_request and osd_req pointers
in the caller's context.

Stat requests go to the HEAD because they are only involved for
a layered write, which *cannot* be a snapshot.  I suppose that
is something that could have been (or be) asserted.

Is it guaranteed/required that method calls go to the HEAD?
I'm sure they all do now, but my question is whether there's
a good reason that it will *always* be true.  Maybe it is.

Similarly, rbd_obj_read_sync() is currently used only for
standalone object requests.  But it's conceivable it could
be useful for image objects.  (I'm not too concerned about
that though...)

Anwyay, this looks fine.  My reservations are all about
ensuring these assumptions are clear in the code.  Maybe
a comment or two is warranted.

In any case...

Reviewed-by: Alex Elder <elder@linaro.org>

> Reported-by: David Disseldorp <ddiss@suse.de>
> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
> ---
>  drivers/block/rbd.c | 9 ++-------
>  1 file changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index 03f171067e08..8907ee6342ac 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -1943,11 +1943,10 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
>  
>  static void rbd_osd_req_format_read(struct rbd_obj_request *obj_request)
>  {
> -	struct rbd_img_request *img_request = obj_request->img_request;
>  	struct ceph_osd_request *osd_req = obj_request->osd_req;
>  
> -	if (img_request)
> -		osd_req->r_snapid = img_request->snap_id;
> +	rbd_assert(obj_request_img_data_test(obj_request));
> +	osd_req->r_snapid = obj_request->img_request->snap_id;
>  }
>  
>  static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
> @@ -2929,8 +2928,6 @@ static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request)
>  	stat_request->page_count = page_count;
>  	stat_request->callback = rbd_img_obj_exists_callback;
>  
> -	rbd_osd_req_format_read(stat_request);
> -
>  	rbd_obj_request_submit(stat_request);
>  	return 0;
>  
> @@ -4026,7 +4023,6 @@ static int rbd_obj_method_sync(struct rbd_device *rbd_dev,
>  	osd_req_op_cls_response_data_pages(obj_request->osd_req, 0,
>  					obj_request->pages, inbound_size,
>  					0, false, false);
> -	rbd_osd_req_format_read(obj_request);
>  
>  	rbd_obj_request_submit(obj_request);
>  	ret = rbd_obj_request_wait(obj_request);
> @@ -4265,7 +4261,6 @@ static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
>  					obj_request->length,
>  					obj_request->offset & ~PAGE_MASK,
>  					false, false);
> -	rbd_osd_req_format_read(obj_request);
>  
>  	rbd_obj_request_submit(obj_request);
>  	ret = rbd_obj_request_wait(obj_request);
> 

--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Disseldorp Sept. 26, 2016, 12:05 p.m. UTC | #2
On Mon, 19 Sep 2016 19:03:27 +0200, Ilya Dryomov wrote:

> Accessing obj_request->img_request union field is only valid for object
> requests associated with an image (i.e. if obj_request_img_data_test()
> returns true).  rbd_osd_req_format_read() used to do more, but now it
> just sets osd_req->snap_id.  Standalone and stat object requests always
> go to the HEAD revision and are fine with CEPH_NOSNAP set by libceph,
> so get around the invalid union field use by simply not calling
> rbd_osd_req_format_read() in those places.
> 
> Reported-by: David Disseldorp <ddiss@suse.de>
> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>

Looks fine.
Reviewed-by: David Disseldorp <ddiss@suse.de>
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ilya Dryomov Sept. 26, 2016, 4:37 p.m. UTC | #3
On Sun, Sep 25, 2016 at 6:44 PM, Alex Elder <elder@linaro.org> wrote:
> On 09/19/2016 12:03 PM, Ilya Dryomov wrote:
>> Accessing obj_request->img_request union field is only valid for object
>> requests associated with an image (i.e. if obj_request_img_data_test()
>> returns true).  rbd_osd_req_format_read() used to do more, but now it
>> just sets osd_req->snap_id.  Standalone and stat object requests always
>> go to the HEAD revision and are fine with CEPH_NOSNAP set by libceph,
>> so get around the invalid union field use by simply not calling
>> rbd_osd_req_format_read() in those places.
>
> Since rbd_osd_req_format_{read,write} are now only called
> from rbd_img_obj_request_fill(), and they're really simple,
> maybe they could be eliminated entirely and open-coded
> instead.  We already have the img_request and osd_req pointers
> in the caller's context.
>
> Stat requests go to the HEAD because they are only involved for
> a layered write, which *cannot* be a snapshot.  I suppose that
> is something that could have been (or be) asserted.

The only reason it's working is img_request->snap_id has the same
offset as obj_request->img_request and we end up setting stat snap_id
to a kernel pointer.  A snapshot with an id like 0xffff...  can't
practically exist, so we get the HEAD response from the OSDs.

>
> Is it guaranteed/required that method calls go to the HEAD?
> I'm sure they all do now, but my question is whether there's
> a good reason that it will *always* be true.  Maybe it is.
>
> Similarly, rbd_obj_read_sync() is currently used only for
> standalone object requests.  But it's conceivable it could
> be useful for image objects.  (I'm not too concerned about
> that though...)
>
> Anwyay, this looks fine.  My reservations are all about
> ensuring these assumptions are clear in the code.  Maybe
> a comment or two is warranted.

libceph initializes snap_id to CEPH_NOSNAP - that's the API.  If the
client isn't setting it, the assumption is clear - HEAD.

Thanks,

                Ilya
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alex Elder Sept. 27, 2016, 5:11 p.m. UTC | #4
On 09/26/2016 11:37 AM, Ilya Dryomov wrote:
> On Sun, Sep 25, 2016 at 6:44 PM, Alex Elder <elder@linaro.org> wrote:
>> On 09/19/2016 12:03 PM, Ilya Dryomov wrote:
>>> Accessing obj_request->img_request union field is only valid for object
>>> requests associated with an image (i.e. if obj_request_img_data_test()
>>> returns true).  rbd_osd_req_format_read() used to do more, but now it
>>> just sets osd_req->snap_id.  Standalone and stat object requests always
>>> go to the HEAD revision and are fine with CEPH_NOSNAP set by libceph,
>>> so get around the invalid union field use by simply not calling
>>> rbd_osd_req_format_read() in those places.
>>
>> Since rbd_osd_req_format_{read,write} are now only called
>> from rbd_img_obj_request_fill(), and they're really simple,
>> maybe they could be eliminated entirely and open-coded
>> instead.  We already have the img_request and osd_req pointers
>> in the caller's context.
>>
>> Stat requests go to the HEAD because they are only involved for
>> a layered write, which *cannot* be a snapshot.  I suppose that
>> is something that could have been (or be) asserted.
> 
> The only reason it's working is img_request->snap_id has the same
> offset as obj_request->img_request and we end up setting stat snap_id

Oh wow.  I wasn't even thinking about that.  I was focusing on
the fact that you're no longer calling rbd_osd_req_format_read()
in those two places.  (Looking again, I see the first sentence
in your description talks about the invalid use of that field.)
So yes, clearly we need to test the IMG_DATA flag before using
the image request pointer.

Aside from that what I said is still true.  Any write *must*
be going to a HEAD object.  And yes, the standalone object
requests go to the HEAD object, but there's nothing that
really requires that

Thanks for the explanation.  This is a good fix.

					-Alex

> to a kernel pointer.  A snapshot with an id like 0xffff...  can't
> practically exist, so we get the HEAD response from the OSDs.
> 
>>
>> Is it guaranteed/required that method calls go to the HEAD?
>> I'm sure they all do now, but my question is whether there's
>> a good reason that it will *always* be true.  Maybe it is.
>>
>> Similarly, rbd_obj_read_sync() is currently used only for
>> standalone object requests.  But it's conceivable it could
>> be useful for image objects.  (I'm not too concerned about
>> that though...)
>>
>> Anwyay, this looks fine.  My reservations are all about
>> ensuring these assumptions are clear in the code.  Maybe
>> a comment or two is warranted.
> 
> libceph initializes snap_id to CEPH_NOSNAP - that's the API.  If the
> client isn't setting it, the assumption is clear - HEAD.
> 
> Thanks,
> 
>                 Ilya
> 

--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 03f171067e08..8907ee6342ac 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1943,11 +1943,10 @@  static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
 
 static void rbd_osd_req_format_read(struct rbd_obj_request *obj_request)
 {
-	struct rbd_img_request *img_request = obj_request->img_request;
 	struct ceph_osd_request *osd_req = obj_request->osd_req;
 
-	if (img_request)
-		osd_req->r_snapid = img_request->snap_id;
+	rbd_assert(obj_request_img_data_test(obj_request));
+	osd_req->r_snapid = obj_request->img_request->snap_id;
 }
 
 static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
@@ -2929,8 +2928,6 @@  static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request)
 	stat_request->page_count = page_count;
 	stat_request->callback = rbd_img_obj_exists_callback;
 
-	rbd_osd_req_format_read(stat_request);
-
 	rbd_obj_request_submit(stat_request);
 	return 0;
 
@@ -4026,7 +4023,6 @@  static int rbd_obj_method_sync(struct rbd_device *rbd_dev,
 	osd_req_op_cls_response_data_pages(obj_request->osd_req, 0,
 					obj_request->pages, inbound_size,
 					0, false, false);
-	rbd_osd_req_format_read(obj_request);
 
 	rbd_obj_request_submit(obj_request);
 	ret = rbd_obj_request_wait(obj_request);
@@ -4265,7 +4261,6 @@  static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
 					obj_request->length,
 					obj_request->offset & ~PAGE_MASK,
 					false, false);
-	rbd_osd_req_format_read(obj_request);
 
 	rbd_obj_request_submit(obj_request);
 	ret = rbd_obj_request_wait(obj_request);